FEAT: Return Playback URL in Get Videos
This commit is contained in:
@@ -3,6 +3,8 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/mediaconvert"
|
||||
@@ -15,6 +17,11 @@ type MediaConvert interface {
|
||||
QueueEncodingJob(ctx context.Context, key string) (string, error)
|
||||
}
|
||||
|
||||
// segmentLengthSeconds is how long each HLS segment runs. Six seconds is the
|
||||
// common default: long enough to keep the playlist and the request count down,
|
||||
// short enough that a player can switch rendition without a long stall.
|
||||
const segmentLengthSeconds = 6
|
||||
|
||||
type MediaConvertConcrete struct {
|
||||
MediaConvertClient *mediaconvert.Client
|
||||
Role string
|
||||
@@ -24,7 +31,14 @@ type MediaConvertConcrete struct {
|
||||
|
||||
func (svc MediaConvertConcrete) QueueEncodingJob(ctx context.Context, key string) (string, error) {
|
||||
input := fmt.Sprintf("s3://%s/%s", svc.InputBucket, key)
|
||||
destination := fmt.Sprintf("s3://%s/%s", svc.OutputBucket, key)
|
||||
|
||||
// HlsGroupSettings.Destination is a *filename base*, not a directory and
|
||||
// not a finished name: MediaConvert appends each output's NameModifier and
|
||||
// the extensions it needs. Giving each video its own folder keeps the
|
||||
// master playlist, the variant playlists and the segments together, and
|
||||
// keeps two videos from interleaving their segments in one prefix.
|
||||
base := strings.TrimSuffix(key, path.Ext(key))
|
||||
destination := fmt.Sprintf("s3://%s/%s/index", svc.OutputBucket, base)
|
||||
|
||||
job, err := svc.MediaConvertClient.CreateJob(ctx, &mediaconvert.CreateJobInput{
|
||||
Role: &svc.Role,
|
||||
@@ -42,24 +56,42 @@ func (svc MediaConvertConcrete) QueueEncodingJob(ctx context.Context, key string
|
||||
},
|
||||
OutputGroups: []types.OutputGroup{
|
||||
{
|
||||
Name: aws.String("File Group"),
|
||||
Name: aws.String("HLS Group"),
|
||||
OutputGroupSettings: &types.OutputGroupSettings{
|
||||
Type: types.OutputGroupTypeFileGroupSettings,
|
||||
FileGroupSettings: &types.FileGroupSettings{
|
||||
Destination: &destination,
|
||||
Type: types.OutputGroupTypeHlsGroupSettings,
|
||||
HlsGroupSettings: &types.HlsGroupSettings{
|
||||
Destination: &destination,
|
||||
SegmentLength: aws.Int32(segmentLengthSeconds),
|
||||
// 0 lets the last segment be as short as it needs to
|
||||
// be rather than padding the ones before it.
|
||||
MinSegmentLength: aws.Int32(0),
|
||||
},
|
||||
},
|
||||
Outputs: []types.Output{
|
||||
{
|
||||
// One rendition. A ladder is another entry here per
|
||||
// rendition, each with its own NameModifier and
|
||||
// height — the master playlist lists whatever is
|
||||
// present, so nothing downstream changes.
|
||||
NameModifier: aws.String("_720p"),
|
||||
ContainerSettings: &types.ContainerSettings{
|
||||
Container: types.ContainerTypeMp4,
|
||||
Container: types.ContainerTypeM3u8,
|
||||
M3u8Settings: &types.M3u8Settings{},
|
||||
},
|
||||
VideoDescription: &types.VideoDescription{
|
||||
Height: aws.Int32(720),
|
||||
CodecSettings: &types.VideoCodecSettings{
|
||||
Codec: types.VideoCodecH264,
|
||||
H264Settings: &types.H264Settings{
|
||||
RateControlMode: types.H264RateControlModeQvbr,
|
||||
MaxBitrate: aws.Int32(5000000),
|
||||
MaxBitrate: aws.Int32(3000000),
|
||||
// A segment has to start on a keyframe,
|
||||
// so the GOP is pinned to a divisor of
|
||||
// the segment length. Left to follow the
|
||||
// source, segments come out uneven and
|
||||
// players stall at the joins.
|
||||
GopSizeUnits: types.H264GopSizeUnitsSeconds,
|
||||
GopSize: aws.Float64(2),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user