Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stub "Transcode Complete" callback #35

Merged
merged 8 commits into from
Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 90 additions & 8 deletions clients/callback_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand All @@ -157,3 +176,66 @@ 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"`
Unretriable bool `json:"unretriable,omitempty"`
Status string `json:"status"`
Timestamp int64 `json:"timestamp"`
}

type VideoTrack struct {
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,omitempty"`
SampleRate int `json:"sample_rate,omitempty"`
}

type InputTrack struct {
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

// Fields only used if this is an Audio Track
AudioTrack
}

type InputVideo struct {
thomshutt marked this conversation as resolved.
Show resolved Hide resolved
Format string `json:"format"`
Tracks []InputTrack `json:"tracks"`
Duration float64 `json:"duration"`
SizeBytes int `json:"size"`
}

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"`
}
59 changes: 59 additions & 0 deletions handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,5 +207,64 @@ 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.InputTrack{
{
Type: "video",
Codec: "h264",
DurationSec: 1.6,
Bitrate: 358315,
VideoTrack: clients.VideoTrack{
FPS: 30,
Width: 1920,
Height: 1080,
PixelFormat: "yuv420p",
},
},
{
Type: "audio",
Codec: "aac",
Bitrate: 141341,
DurationSec: 1.599979,
AudioTrack: clients.AudioTrack{
Channels: 2,
SampleRate: 48000,
},
},
},
},
[]clients.OutputVideo{
{
Type: "google-s3",
Manifest: "s3://livepeer-studio-uploads/videos/<video-id>/master.m3u8",
Videos: []clients.OutputVideoFile{
{
Type: "mp4",
SizeBytes: 12345,
Location: "s3://livepeer-studio-uploads/videos/<video-id>/video-480p.mp4",
},
},
},
},
)
}