From ebccfff7da4a7019c6052ff15e08b500583b9247 Mon Sep 17 00:00:00 2001 From: Thom Shutt Date: Tue, 6 Sep 2022 21:47:49 +0100 Subject: [PATCH 1/8] Stub callbacks for Studio to integrate against --- clients/callback_client.go | 84 ++++++++++++++++++++++++++++++++++---- handlers/handlers.go | 55 +++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 8 deletions(-) diff --git a/clients/callback_client.go b/clients/callback_client.go index 527f2e450..77956dca8 100644 --- a/clients/callback_client.go +++ b/clients/callback_client.go @@ -90,6 +90,33 @@ func (c CallbackClient) SendTranscodeStatusError(callbackURL, errorMsg string) e return c.DoWithRetries(r) } +// Separate method as this requires a much richer message than the other status callbacks +func (c CallbackClient) SendTranscodeStatusCompleted(url string, iv InputVideo, ov []OutputVideo) error { + tsm := TranscodeStatusCompletedMessage{ + TranscodeStatusMessage: TranscodeStatusMessage{ + CompletionRatio: overallCompletionRatio(TranscodeStatusCompleted, 1), + Status: TranscodeStatusCompleted.String(), + Timestamp: config.Clock.GetTimestampUTC(), + }, + Type: "video", // Assume everything is a video for now + InputVideo: iv, + Outputs: ov, + } + + j, err := json.Marshal(tsm) + if err != nil { + return err + } + + r, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(j)) + if err != nil { + return err + } + + return c.DoWithRetries(r) + +} + // Calculate the overall completion ratio based on the completion ratio of the current stage. // The weighting will need to be tweaked as we understand better the relative time spent in the // segmenting vs. transcoding stages. @@ -134,14 +161,6 @@ const ( TranscodeStatusError ) -type TranscodeStatusMessage struct { - CompletionRatio float64 `json:"completion_ratio"` // No omitempty or we lose this for 0% completion case - Error string `json:"error,omitempty"` - Retriable *bool `json:"retriable,omitempty"` // Has to be a pointer or we can't differentiate omission from 'false' - Status string `json:"status,omitempty"` - Timestamp int64 `json:"timestamp"` -} - func (ts TranscodeStatus) String() string { switch ts { case TranscodeStatusPreparing: @@ -157,3 +176,52 @@ func (ts TranscodeStatus) String() string { } return "unknown" } + +// The various status messages we can send + +type TranscodeStatusMessage struct { + CompletionRatio float64 `json:"completion_ratio"` // No omitempty or we lose this for 0% completion case + Error string `json:"error,omitempty"` + Retriable *bool `json:"retriable,omitempty"` // Has to be a pointer or we can't differentiate omission from 'false' + Status string `json:"status,omitempty"` + Timestamp int64 `json:"timestamp"` +} + +type InputVideoTrack struct { + Fps int `json:"fps,omitempty"` + Type string `json:"type,omitempty"` + Codec string `json:"codec,omitempty"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + Bitrate int `json:"bitrate,omitempty"` + Duration float64 `json:"duration,omitempty"` + PixelFormat string `json:"pixel_format,omitempty"` + Channels int `json:"channels,omitempty"` + SampleRate int `json:"sampleRate,omitempty"` + SizeBytes int `json:"size,omitempty"` +} + +type InputVideo struct { + Format string `json:"format"` + Tracks []InputVideoTrack `json:"tracks"` + Duration float64 `json:"duration"` +} + +type OutputVideoFile struct { + Type string `json:"type"` + SizeBytes int `json:"size"` + Location string `json:"location"` +} + +type OutputVideo struct { + Type string `json:"type"` + Manifest string `json:"manifest"` + Videos []OutputVideoFile `json:"videos"` +} + +type TranscodeStatusCompletedMessage struct { + TranscodeStatusMessage + Type string `json:"type"` + InputVideo InputVideo `json:"video_spec"` + Outputs []OutputVideo `json:"outputs"` +} diff --git a/handlers/handlers.go b/handlers/handlers.go index 0f53d0490..f664042ed 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -207,5 +207,60 @@ func (d *MistCallbackHandlersCollection) Trigger() httprouter.Handle { // TODO: add timeout for the stream upload // TODO: start transcoding + stubTranscodingCallbacksForStudio(d.StreamCache[s].callbackUrl, callbackClient) } } + +// This method is for Studio to have something to integrate with and to make sure we have all the callbacks +// in place that we'll need +func stubTranscodingCallbacksForStudio(callbackURL string, callbackClient clients.CallbackClient) { + time.Sleep(5 * time.Second) + callbackClient.SendTranscodeStatus(callbackURL, clients.TranscodeStatusTranscoding, 0.3) + time.Sleep(5 * time.Second) + callbackClient.SendTranscodeStatus(callbackURL, clients.TranscodeStatusTranscoding, 0.6) + time.Sleep(5 * time.Second) + callbackClient.SendTranscodeStatus(callbackURL, clients.TranscodeStatusTranscoding, 0.9) + time.Sleep(5 * time.Second) + callbackClient.SendTranscodeStatus(callbackURL, clients.TranscodeStatusTranscoding, 1) + time.Sleep(5 * time.Second) + callbackClient.SendTranscodeStatusCompleted( + callbackURL, + clients.InputVideo{ + Format: "mp4", + Duration: 1234.5678, + Tracks: []clients.InputVideoTrack{ + { + Fps: 30, + Type: "video", + Codec: "h264", + Width: 1920, + Height: 1080, + Bitrate: 358315, + Duration: 1.6, + PixelFormat: "yuv420p", + }, + { + Type: "audio", + Codec: "aac", + Bitrate: 141341, + Channels: 2, + Duration: 1.599979, + SampleRate: 48000, + }, + }, + }, + []clients.OutputVideo{ + { + Type: "google-s3", + Manifest: "s3://livepeer-studio-uploads/videos//master.m3u8", + Videos: []clients.OutputVideoFile{ + { + Type: "mp4", + SizeBytes: 12345, + Location: "s3://livepeer-studio-uploads/videos//video-480p.mp4", + }, + }, + }, + }, + ) +} From ffd07e8bbb874a1ca60ba9f06c05c92768e1b9d6 Mon Sep 17 00:00:00 2001 From: Thom Shutt Date: Tue, 6 Sep 2022 22:51:50 +0100 Subject: [PATCH 2/8] Retriable -> Unretriable --- clients/callback_client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/callback_client.go b/clients/callback_client.go index 77956dca8..8fb5f6657 100644 --- a/clients/callback_client.go +++ b/clients/callback_client.go @@ -182,7 +182,7 @@ func (ts TranscodeStatus) String() string { type TranscodeStatusMessage struct { CompletionRatio float64 `json:"completion_ratio"` // No omitempty or we lose this for 0% completion case Error string `json:"error,omitempty"` - Retriable *bool `json:"retriable,omitempty"` // Has to be a pointer or we can't differentiate omission from 'false' + Unretriable bool `json:"unretriable,omitempty"` Status string `json:"status,omitempty"` Timestamp int64 `json:"timestamp"` } From 60c6ff73215343bade29cf5193f2ec37f4465d10 Mon Sep 17 00:00:00 2001 From: Thom Shutt Date: Tue, 6 Sep 2022 22:52:32 +0100 Subject: [PATCH 3/8] snake_case --- clients/callback_client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/callback_client.go b/clients/callback_client.go index 8fb5f6657..eb3f1fd6b 100644 --- a/clients/callback_client.go +++ b/clients/callback_client.go @@ -197,7 +197,7 @@ type InputVideoTrack struct { Duration float64 `json:"duration,omitempty"` PixelFormat string `json:"pixel_format,omitempty"` Channels int `json:"channels,omitempty"` - SampleRate int `json:"sampleRate,omitempty"` + SampleRate int `json:"sample_rate,omitempty"` SizeBytes int `json:"size,omitempty"` } From b58c4b10032005d9f70a10d720a888c67040408c Mon Sep 17 00:00:00 2001 From: Thom Shutt Date: Tue, 6 Sep 2022 22:54:38 +0100 Subject: [PATCH 4/8] Add size to input struct --- clients/callback_client.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clients/callback_client.go b/clients/callback_client.go index eb3f1fd6b..e255ef611 100644 --- a/clients/callback_client.go +++ b/clients/callback_client.go @@ -202,9 +202,10 @@ type InputVideoTrack struct { } type InputVideo struct { - Format string `json:"format"` - Tracks []InputVideoTrack `json:"tracks"` - Duration float64 `json:"duration"` + Format string `json:"format"` + Tracks []InputVideoTrack `json:"tracks"` + Duration float64 `json:"duration"` + SizeBytes float64 `json:"size"` } type OutputVideoFile struct { From 150681e6b1f085a59b85460cbf7970d50cb55268 Mon Sep 17 00:00:00 2001 From: Thom Shutt Date: Tue, 6 Sep 2022 22:55:01 +0100 Subject: [PATCH 5/8] Add size to input struct --- clients/callback_client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/callback_client.go b/clients/callback_client.go index e255ef611..1a8af30d9 100644 --- a/clients/callback_client.go +++ b/clients/callback_client.go @@ -205,7 +205,7 @@ type InputVideo struct { Format string `json:"format"` Tracks []InputVideoTrack `json:"tracks"` Duration float64 `json:"duration"` - SizeBytes float64 `json:"size"` + SizeBytes int `json:"size"` } type OutputVideoFile struct { From 70be82037be1362410cb6a5d2ab8a4a465e7aa94 Mon Sep 17 00:00:00 2001 From: Thom Shutt Date: Tue, 6 Sep 2022 23:08:08 +0100 Subject: [PATCH 6/8] Remove omitemptys and structure struct to split out audio/video fields --- clients/callback_client.go | 46 ++++++++++++++++++++++++-------------- handlers/handlers.go | 28 +++++++++++++---------- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/clients/callback_client.go b/clients/callback_client.go index 1a8af30d9..9754c4aa8 100644 --- a/clients/callback_client.go +++ b/clients/callback_client.go @@ -183,29 +183,41 @@ type TranscodeStatusMessage struct { CompletionRatio float64 `json:"completion_ratio"` // No omitempty or we lose this for 0% completion case Error string `json:"error,omitempty"` Unretriable bool `json:"unretriable,omitempty"` - Status string `json:"status,omitempty"` + Status string `json:"status"` Timestamp int64 `json:"timestamp"` } -type InputVideoTrack struct { - Fps int `json:"fps,omitempty"` - Type string `json:"type,omitempty"` - Codec string `json:"codec,omitempty"` - Width int `json:"width,omitempty"` - Height int `json:"height,omitempty"` - Bitrate int `json:"bitrate,omitempty"` - Duration float64 `json:"duration,omitempty"` - PixelFormat string `json:"pixel_format,omitempty"` - Channels int `json:"channels,omitempty"` - SampleRate int `json:"sample_rate,omitempty"` - SizeBytes int `json:"size,omitempty"` +type VideoTrack struct { + Width int `json:"width"` + Height int `json:"height"` + PixelFormat string `json:"pixel_format"` + FPS int `json:"fps"` +} + +type AudioTrack struct { + Channels int `json:"channels"` + SampleRate int `json:"sample_rate"` +} + +type InputTrack struct { + Type string `json:"type"` + Codec string `json:"codec"` + Bitrate int `json:"bitrate"` + DurationSec float64 `json:"duration"` + SizeBytes int `json:"size"` + + // Fields only used if this is a Video Track + VideoTrack + + // Fields only used if this is an Audio Track + AudioTrack } type InputVideo struct { - Format string `json:"format"` - Tracks []InputVideoTrack `json:"tracks"` - Duration float64 `json:"duration"` - SizeBytes int `json:"size"` + Format string `json:"format"` + Tracks []InputTrack `json:"tracks"` + Duration float64 `json:"duration"` + SizeBytes int `json:"size"` } type OutputVideoFile struct { diff --git a/handlers/handlers.go b/handlers/handlers.go index f664042ed..92b726fb0 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -228,24 +228,28 @@ func stubTranscodingCallbacksForStudio(callbackURL string, callbackClient client clients.InputVideo{ Format: "mp4", Duration: 1234.5678, - Tracks: []clients.InputVideoTrack{ + Tracks: []clients.InputTrack{ { - Fps: 30, Type: "video", Codec: "h264", - Width: 1920, - Height: 1080, + DurationSec: 1.6, Bitrate: 358315, - Duration: 1.6, - PixelFormat: "yuv420p", + VideoTrack: clients.VideoTrack{ + FPS: 30, + Width: 1920, + Height: 1080, + PixelFormat: "yuv420p", + }, }, { - Type: "audio", - Codec: "aac", - Bitrate: 141341, - Channels: 2, - Duration: 1.599979, - SampleRate: 48000, + Type: "audio", + Codec: "aac", + Bitrate: 141341, + DurationSec: 1.599979, + AudioTrack: clients.AudioTrack{ + Channels: 2, + SampleRate: 48000, + }, }, }, }, From 861dca3cfd08b829643e2b8c9be516b4dc384ef4 Mon Sep 17 00:00:00 2001 From: Thom Shutt Date: Wed, 7 Sep 2022 11:19:09 +0100 Subject: [PATCH 7/8] Omitempty on audio/video specific fields --- clients/callback_client.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clients/callback_client.go b/clients/callback_client.go index 9754c4aa8..205c4e57b 100644 --- a/clients/callback_client.go +++ b/clients/callback_client.go @@ -188,15 +188,15 @@ type TranscodeStatusMessage struct { } type VideoTrack struct { - Width int `json:"width"` - Height int `json:"height"` - PixelFormat string `json:"pixel_format"` - FPS int `json:"fps"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + PixelFormat string `json:"pixel_format,omitempty"` + FPS int `json:"fps,omitempty"` } type AudioTrack struct { - Channels int `json:"channels"` - SampleRate int `json:"sample_rate"` + Channels int `json:"channels,omitempty"` + SampleRate int `json:"sample_rate,omitempty"` } type InputTrack struct { From 88215626410a529e8e76d2f8bc355c5adf78063d Mon Sep 17 00:00:00 2001 From: Thom Shutt Date: Wed, 7 Sep 2022 11:20:08 +0100 Subject: [PATCH 8/8] Add start time field to track --- clients/callback_client.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clients/callback_client.go b/clients/callback_client.go index 205c4e57b..b42550adf 100644 --- a/clients/callback_client.go +++ b/clients/callback_client.go @@ -200,11 +200,12 @@ type AudioTrack struct { } type InputTrack struct { - Type string `json:"type"` - Codec string `json:"codec"` - Bitrate int `json:"bitrate"` - DurationSec float64 `json:"duration"` - SizeBytes int `json:"size"` + Type string `json:"type"` + Codec string `json:"codec"` + Bitrate int `json:"bitrate"` + DurationSec float64 `json:"duration"` + SizeBytes int `json:"size"` + StartTimeSec float64 `json:"start_time"` // Fields only used if this is a Video Track VideoTrack