Added codec-aware encoding profiles and moved pixel format to per-variant output.
Encoders now receive the codec being used, allowing them to adjust their flags accordingly. For example, the software encoder gates x264-specific parameters behind a codec check so that future encoders like libx265 or libsvtav1 can provide their own flags without conflict. Pixel format is now specified per variant with a stream specifier rather than globally, enabling codecs like AV1 to use 10-bit color for improved compression efficiency while H.264 variants continue using yuv420p.
This commit is contained in:
+33
-22
@@ -11,15 +11,20 @@ const (
|
|||||||
ffmpegEncoderX264 = "libx264"
|
ffmpegEncoderX264 = "libx264"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CodecProfile holds codec-dependent encoding parameters for an encoder.
|
||||||
|
type CodecProfile struct {
|
||||||
|
PixelFormat string
|
||||||
|
Scaler string
|
||||||
|
ExtraFilters string
|
||||||
|
}
|
||||||
|
|
||||||
// Encoder represents a hardware/software video encoding backend (e.g., software CPU, NVENC, VA-API).
|
// Encoder represents a hardware/software video encoding backend (e.g., software CPU, NVENC, VA-API).
|
||||||
type Encoder interface {
|
type Encoder interface {
|
||||||
Name() string
|
Name() string
|
||||||
DisplayName() string
|
DisplayName() string
|
||||||
GlobalFlags() []string
|
GlobalFlags() []string
|
||||||
PixelFormat() string
|
|
||||||
Scaler() string
|
|
||||||
ExtraFilters() string
|
|
||||||
ExtraArguments() []string
|
ExtraArguments() []string
|
||||||
|
ProfileForCodec(codec string) CodecProfile
|
||||||
VariantFlags(v *HLSVariant) []string
|
VariantFlags(v *HLSVariant) []string
|
||||||
SupportedVideoCodecs() []string
|
SupportedVideoCodecs() []string
|
||||||
FFmpegEncoderForCodec(codec string) string
|
FFmpegEncoderForCodec(codec string) string
|
||||||
@@ -41,31 +46,37 @@ func (e *SoftwareEncoder) GlobalFlags() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *SoftwareEncoder) PixelFormat() string {
|
|
||||||
return pixelFormatYUV420P
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SoftwareEncoder) Scaler() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SoftwareEncoder) ExtraFilters() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SoftwareEncoder) ExtraArguments() []string {
|
func (e *SoftwareEncoder) ExtraArguments() []string {
|
||||||
return []string{
|
return []string{"-tune", "zerolatency"}
|
||||||
"-tune", "zerolatency",
|
}
|
||||||
|
|
||||||
|
func (e *SoftwareEncoder) ProfileForCodec(codec string) CodecProfile {
|
||||||
|
return CodecProfile{
|
||||||
|
PixelFormat: pixelFormatYUV420P,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *SoftwareEncoder) VariantFlags(v *HLSVariant) []string {
|
func (e *SoftwareEncoder) VariantFlags(v *HLSVariant) []string {
|
||||||
return []string{
|
codec := v.videoCodec.Name()
|
||||||
fmt.Sprintf("-x264-params:v:%d", v.index),
|
var flags []string
|
||||||
"scenecut=0:open_gop=0",
|
|
||||||
fmt.Sprintf("-bufsize:v:%d", v.index), fmt.Sprintf("%dk", v.getBufferSize()),
|
if codec == videoCodecH264 {
|
||||||
fmt.Sprintf("-profile:v:%d", v.index), "high",
|
flags = append(flags,
|
||||||
|
fmt.Sprintf("-x264-params:v:%d", v.index), "scenecut=0:open_gop=0",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flags = append(flags,
|
||||||
|
fmt.Sprintf("-bufsize:v:%d", v.index), fmt.Sprintf("%dk", v.getBufferSize()),
|
||||||
|
)
|
||||||
|
|
||||||
|
if codec == videoCodecH264 {
|
||||||
|
flags = append(flags,
|
||||||
|
fmt.Sprintf("-profile:v:%d", v.index), "high",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *SoftwareEncoder) SupportedVideoCodecs() []string {
|
func (e *SoftwareEncoder) SupportedVideoCodecs() []string {
|
||||||
|
|||||||
@@ -23,22 +23,16 @@ func (e *NvencEncoder) GlobalFlags() []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *NvencEncoder) PixelFormat() string {
|
|
||||||
return pixelFormatYUV420P
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *NvencEncoder) Scaler() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *NvencEncoder) ExtraFilters() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *NvencEncoder) ExtraArguments() []string {
|
func (e *NvencEncoder) ExtraArguments() []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *NvencEncoder) ProfileForCodec(codec string) CodecProfile {
|
||||||
|
return CodecProfile{
|
||||||
|
PixelFormat: pixelFormatYUV420P,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *NvencEncoder) VariantFlags(v *HLSVariant) []string {
|
func (e *NvencEncoder) VariantFlags(v *HLSVariant) []string {
|
||||||
return []string{
|
return []string{
|
||||||
fmt.Sprintf("-tune:v:%d", v.index), "ll",
|
fmt.Sprintf("-tune:v:%d", v.index), "ll",
|
||||||
|
|||||||
@@ -17,21 +17,13 @@ func (e *OmxEncoder) GlobalFlags() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *OmxEncoder) PixelFormat() string {
|
|
||||||
return pixelFormatYUV420P
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *OmxEncoder) Scaler() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *OmxEncoder) ExtraFilters() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *OmxEncoder) ExtraArguments() []string {
|
func (e *OmxEncoder) ExtraArguments() []string {
|
||||||
return []string{
|
return []string{"-tune", "zerolatency"}
|
||||||
"-tune", "zerolatency",
|
}
|
||||||
|
|
||||||
|
func (e *OmxEncoder) ProfileForCodec(codec string) CodecProfile {
|
||||||
|
return CodecProfile{
|
||||||
|
PixelFormat: pixelFormatYUV420P,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,22 +20,18 @@ func (e *QuicksyncEncoder) GlobalFlags() []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *QuicksyncEncoder) PixelFormat() string {
|
|
||||||
return "qsv"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *QuicksyncEncoder) Scaler() string {
|
|
||||||
return "scale_qsv"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *QuicksyncEncoder) ExtraFilters() string {
|
|
||||||
return "hwupload=extra_hw_frames=64,format=qsv"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *QuicksyncEncoder) ExtraArguments() []string {
|
func (e *QuicksyncEncoder) ExtraArguments() []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *QuicksyncEncoder) ProfileForCodec(codec string) CodecProfile {
|
||||||
|
return CodecProfile{
|
||||||
|
PixelFormat: "qsv",
|
||||||
|
Scaler: "scale_qsv",
|
||||||
|
ExtraFilters: "hwupload=extra_hw_frames=64,format=qsv",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *QuicksyncEncoder) VariantFlags(v *HLSVariant) []string {
|
func (e *QuicksyncEncoder) VariantFlags(v *HLSVariant) []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,22 +17,16 @@ func (e *V4l2m2mEncoder) GlobalFlags() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *V4l2m2mEncoder) PixelFormat() string {
|
|
||||||
return "nv21"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *V4l2m2mEncoder) Scaler() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *V4l2m2mEncoder) ExtraFilters() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *V4l2m2mEncoder) ExtraArguments() []string {
|
func (e *V4l2m2mEncoder) ExtraArguments() []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *V4l2m2mEncoder) ProfileForCodec(codec string) CodecProfile {
|
||||||
|
return CodecProfile{
|
||||||
|
PixelFormat: "nv21",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *V4l2m2mEncoder) VariantFlags(v *HLSVariant) []string {
|
func (e *V4l2m2mEncoder) VariantFlags(v *HLSVariant) []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,22 +21,18 @@ func (e *VaapiEncoder) GlobalFlags() []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *VaapiEncoder) PixelFormat() string {
|
|
||||||
return "vaapi"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *VaapiEncoder) Scaler() string {
|
|
||||||
return "scale_vaapi"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *VaapiEncoder) ExtraFilters() string {
|
|
||||||
return "hwupload=extra_hw_frames=64,format=vaapi"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *VaapiEncoder) ExtraArguments() []string {
|
func (e *VaapiEncoder) ExtraArguments() []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *VaapiEncoder) ProfileForCodec(codec string) CodecProfile {
|
||||||
|
return CodecProfile{
|
||||||
|
PixelFormat: "vaapi",
|
||||||
|
Scaler: "scale_vaapi",
|
||||||
|
ExtraFilters: "hwupload=extra_hw_frames=64,format=vaapi",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *VaapiEncoder) VariantFlags(v *HLSVariant) []string {
|
func (e *VaapiEncoder) VariantFlags(v *HLSVariant) []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,22 +17,16 @@ func (e *VideoToolboxEncoder) GlobalFlags() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *VideoToolboxEncoder) PixelFormat() string {
|
|
||||||
return "nv12"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *VideoToolboxEncoder) Scaler() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *VideoToolboxEncoder) ExtraFilters() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *VideoToolboxEncoder) ExtraArguments() []string {
|
func (e *VideoToolboxEncoder) ExtraArguments() []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *VideoToolboxEncoder) ProfileForCodec(codec string) CodecProfile {
|
||||||
|
return CodecProfile{
|
||||||
|
PixelFormat: "nv12",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (e *VideoToolboxEncoder) VariantFlags(v *HLSVariant) []string {
|
func (e *VideoToolboxEncoder) VariantFlags(v *HLSVariant) []string {
|
||||||
if v.cpuUsageLevel >= 3 {
|
if v.cpuUsageLevel >= 3 {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -254,7 +254,6 @@ func (t *Transcoder) getFlags() *execInfo {
|
|||||||
|
|
||||||
ffmpegFlags = append(ffmpegFlags, []string{
|
ffmpegFlags = append(ffmpegFlags, []string{
|
||||||
// Video settings
|
// Video settings
|
||||||
"-pix_fmt", t.encoder.PixelFormat(),
|
|
||||||
"-sc_threshold", "0", // Disable scene change detection for creating segments
|
"-sc_threshold", "0", // Disable scene change detection for creating segments
|
||||||
|
|
||||||
// Filenames
|
// Filenames
|
||||||
@@ -343,22 +342,24 @@ func (v *HLSVariant) getVariantString(t *Transcoder) []string {
|
|||||||
variantEncoderCommands := v.getVideoQualityString(t)
|
variantEncoderCommands := v.getVideoQualityString(t)
|
||||||
variantEncoderCommands = append(variantEncoderCommands, v.getAudioQualityString()...)
|
variantEncoderCommands = append(variantEncoderCommands, v.getAudioQualityString()...)
|
||||||
|
|
||||||
|
profile := t.encoder.ProfileForCodec(v.videoCodec.Name())
|
||||||
|
|
||||||
if (v.videoSize.Width != 0 || v.videoSize.Height != 0) && !v.isVideoPassthrough {
|
if (v.videoSize.Width != 0 || v.videoSize.Height != 0) && !v.isVideoPassthrough {
|
||||||
// Order here matters, you must scale before changing hardware formats
|
// Order here matters, you must scale before changing hardware formats
|
||||||
filters := []string{
|
filters := []string{
|
||||||
v.getScalingString(t.encoder.Scaler()),
|
v.getScalingString(profile.Scaler),
|
||||||
}
|
}
|
||||||
if t.encoder.ExtraFilters() != "" {
|
if profile.ExtraFilters != "" {
|
||||||
filters = append(filters, t.encoder.ExtraFilters())
|
filters = append(filters, profile.ExtraFilters)
|
||||||
}
|
}
|
||||||
scalingAlgorithm := "bilinear"
|
scalingAlgorithm := "bilinear"
|
||||||
variantEncoderCommands = append(variantEncoderCommands, []string{
|
variantEncoderCommands = append(variantEncoderCommands, []string{
|
||||||
"-sws_flags", scalingAlgorithm,
|
"-sws_flags", scalingAlgorithm,
|
||||||
"-filter:v:" + strconv.Itoa(v.index), strings.Join(filters, ","),
|
"-filter:v:" + strconv.Itoa(v.index), strings.Join(filters, ","),
|
||||||
}...)
|
}...)
|
||||||
} else if t.encoder.ExtraFilters() != "" && !v.isVideoPassthrough {
|
} else if profile.ExtraFilters != "" && !v.isVideoPassthrough {
|
||||||
variantEncoderCommands = append(variantEncoderCommands, []string{
|
variantEncoderCommands = append(variantEncoderCommands, []string{
|
||||||
"-filter:v:" + strconv.Itoa(v.index), t.encoder.ExtraFilters(),
|
"-filter:v:" + strconv.Itoa(v.index), profile.ExtraFilters,
|
||||||
}...)
|
}...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,13 +422,16 @@ func (v *HLSVariant) getVideoQualityString(t *Transcoder) []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ffmpegEncoder := t.encoder.FFmpegEncoderForCodec(v.videoCodec.Name())
|
codec := v.videoCodec.Name()
|
||||||
|
ffmpegEncoder := t.encoder.FFmpegEncoderForCodec(codec)
|
||||||
|
profile := t.encoder.ProfileForCodec(codec)
|
||||||
|
|
||||||
gop := v.framerate * t.currentLatencyLevel.SecondsPerSegment // force an i-frame every segment
|
gop := v.framerate * t.currentLatencyLevel.SecondsPerSegment // force an i-frame every segment
|
||||||
cmd := make([]string, 0, 20)
|
cmd := make([]string, 0, 20)
|
||||||
cmd = append(cmd,
|
cmd = append(cmd,
|
||||||
"-map", "v:0",
|
"-map", "v:0",
|
||||||
fmt.Sprintf("-c:v:%d", v.index), ffmpegEncoder, // Video encoder used for this variant
|
fmt.Sprintf("-c:v:%d", v.index), ffmpegEncoder, // Video encoder used for this variant
|
||||||
|
fmt.Sprintf("-pix_fmt:v:%d", v.index), profile.PixelFormat, // Pixel format for this variant
|
||||||
fmt.Sprintf("-b:v:%d", v.index), fmt.Sprintf("%dk", v.getAllocatedVideoBitrate()), // The average bitrate for this variant allowing space for audio
|
fmt.Sprintf("-b:v:%d", v.index), fmt.Sprintf("%dk", v.getAllocatedVideoBitrate()), // The average bitrate for this variant allowing space for audio
|
||||||
fmt.Sprintf("-maxrate:v:%d", v.index), fmt.Sprintf("%dk", v.getMaxVideoBitrate()), // The max bitrate allowed for this variant
|
fmt.Sprintf("-maxrate:v:%d", v.index), fmt.Sprintf("%dk", v.getMaxVideoBitrate()), // The max bitrate allowed for this variant
|
||||||
fmt.Sprintf("-g:v:%d", v.index), fmt.Sprintf("%d", gop), // Suggested interval where i-frames are encoded into the segments
|
fmt.Sprintf("-g:v:%d", v.index), fmt.Sprintf("%d", gop), // Suggested interval where i-frames are encoded into the segments
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func TestFFmpegNvencCommand(t *testing.T) {
|
|||||||
cmd := transcoder.GetString()
|
cmd := transcoder.GetString()
|
||||||
|
|
||||||
expectedLogPath := "data/logs/transcoder.log"
|
expectedLogPath := "data/logs/transcoder.log"
|
||||||
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -hwaccel cuda -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_nvenc -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -tune:v:0 ll -map a:0? -c:a:0 copy -preset p3 -map v:0 -c:v:1 h264_nvenc -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -tune:v:1 ll -map a:0? -c:a:1 copy -preset p5 -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset p1 -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -pix_fmt yuv420p -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdoieGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -hwaccel cuda -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_nvenc -pix_fmt:v:0 yuv420p -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -tune:v:0 ll -map a:0? -c:a:0 copy -preset p3 -map v:0 -c:v:1 h264_nvenc -pix_fmt:v:1 yuv420p -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -tune:v:1 ll -map a:0? -c:a:1 copy -preset p5 -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset p1 -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdoieGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
||||||
|
|
||||||
if cmd != expected {
|
if cmd != expected {
|
||||||
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func TestFFmpegOmxCommand(t *testing.T) {
|
|||||||
cmd := transcoder.GetString()
|
cmd := transcoder.GetString()
|
||||||
|
|
||||||
expectedLogPath := "data/logs/transcoder.log"
|
expectedLogPath := "data/logs/transcoder.log"
|
||||||
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_omx -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -map a:0? -c:a:0 copy -preset veryfast -map v:0 -c:v:1 h264_omx -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -tune zerolatency -pix_fmt yuv420p -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdFsdfzGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_omx -pix_fmt:v:0 yuv420p -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -map a:0? -c:a:0 copy -preset veryfast -map v:0 -c:v:1 h264_omx -pix_fmt:v:1 yuv420p -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -tune zerolatency -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdFsdfzGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
||||||
|
|
||||||
if cmd != expected {
|
if cmd != expected {
|
||||||
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func TestFFmpegQuicksyncCommand(t *testing.T) {
|
|||||||
cmd := transcoder.GetString()
|
cmd := transcoder.GetString()
|
||||||
|
|
||||||
expectedLogPath := "data/logs/transcoder.log"
|
expectedLogPath := "data/logs/transcoder.log"
|
||||||
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -init_hw_device qsv=hw -filter_hw_device hw -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_qsv -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -map a:0? -c:a:0 copy -filter:v:0 hwupload=extra_hw_frames=64,format=qsv -preset medium -map v:0 -c:v:1 h264_qsv -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -filter:v:1 hwupload=extra_hw_frames=64,format=qsv -preset veryslow -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset veryfast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -pix_fmt qsv -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdofFGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -init_hw_device qsv=hw -filter_hw_device hw -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_qsv -pix_fmt:v:0 qsv -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -map a:0? -c:a:0 copy -filter:v:0 hwupload=extra_hw_frames=64,format=qsv -preset medium -map v:0 -c:v:1 h264_qsv -pix_fmt:v:1 qsv -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -filter:v:1 hwupload=extra_hw_frames=64,format=qsv -preset veryslow -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset veryfast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdofFGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
||||||
|
|
||||||
if cmd != expected {
|
if cmd != expected {
|
||||||
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func TestFFmpegVaapiCommand(t *testing.T) {
|
|||||||
cmd := transcoder.GetString()
|
cmd := transcoder.GetString()
|
||||||
|
|
||||||
expectedLogPath := "data/logs/transcoder.log"
|
expectedLogPath := "data/logs/transcoder.log"
|
||||||
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device /dev/dri/renderD128 -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_vaapi -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -map a:0? -c:a:0 copy -filter:v:0 hwupload=extra_hw_frames=64,format=vaapi -preset veryfast -map v:0 -c:v:1 h264_vaapi -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -filter:v:1 hwupload=extra_hw_frames=64,format=vaapi -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -pix_fmt vaapi -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdofFGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device /dev/dri/renderD128 -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_vaapi -pix_fmt:v:0 vaapi -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -map a:0? -c:a:0 copy -filter:v:0 hwupload=extra_hw_frames=64,format=vaapi -preset veryfast -map v:0 -c:v:1 h264_vaapi -pix_fmt:v:1 vaapi -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -filter:v:1 hwupload=extra_hw_frames=64,format=vaapi -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdofFGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
||||||
|
|
||||||
if cmd != expected {
|
if cmd != expected {
|
||||||
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func TestFFmpegVideoToolboxCommand(t *testing.T) {
|
|||||||
cmd := transcoder.GetString()
|
cmd := transcoder.GetString()
|
||||||
|
|
||||||
expectedLogPath := "data/logs/transcoder.log"
|
expectedLogPath := "data/logs/transcoder.log"
|
||||||
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_videotoolbox -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -realtime true -map a:0? -c:a:0 copy -preset veryfast -map v:0 -c:v:1 h264_videotoolbox -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -pix_fmt nv12 -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdFsdfzGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_videotoolbox -pix_fmt:v:0 nv12 -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -realtime true -map a:0? -c:a:0 copy -preset veryfast -map v:0 -c:v:1 h264_videotoolbox -pix_fmt:v:1 nv12 -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdFsdfzGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
||||||
|
|
||||||
if cmd != expected {
|
if cmd != expected {
|
||||||
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func TestFFmpegx264Command(t *testing.T) {
|
|||||||
cmd := transcoder.GetString()
|
cmd := transcoder.GetString()
|
||||||
|
|
||||||
expectedLogPath := "data/logs/transcoder.log"
|
expectedLogPath := "data/logs/transcoder.log"
|
||||||
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 libx264 -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -x264-params:v:0 scenecut=0:open_gop=0 -bufsize:v:0 1088k -profile:v:0 high -map a:0? -c:a:0 copy -preset veryfast -map v:0 -c:v:1 libx264 -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -x264-params:v:1 scenecut=0:open_gop=0 -bufsize:v:1 3572k -profile:v:1 high -map a:0? -c:a:1 copy -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -tune zerolatency -pix_fmt yuv420p -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdofFGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
expected := `FFREPORT=file=` + expectedLogPath + `:level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 libx264 -pix_fmt:v:0 yuv420p -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -x264-params:v:0 scenecut=0:open_gop=0 -bufsize:v:0 1088k -profile:v:0 high -map a:0? -c:a:0 copy -preset veryfast -map v:0 -c:v:1 libx264 -pix_fmt:v:1 yuv420p -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -x264-params:v:1 scenecut=0:open_gop=0 -bufsize:v:1 3572k -profile:v:1 high -map a:0? -c:a:1 copy -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map v:0,a:0 v:1,a:1 v:2,a:2 -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -tune zerolatency -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdofFGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8`
|
||||||
|
|
||||||
if cmd != expected {
|
if cmd != expected {
|
||||||
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected)
|
||||||
|
|||||||
Reference in New Issue
Block a user