u2takey / ffmpeg-go

golang binding for ffmpeg
Apache License 2.0
1.6k stars 165 forks source link

Multiple Resolution in m3u8 Playlist #77

Open yusrenaltair opened 1 year ago

yusrenaltair commented 1 year ago

Thanks for this awesome package. I have successfully generated master.m3u8 with multiple resolution playlist (360p, 480p and 720p) with the terminal command below.

ffmpeg -i source.mp4 \
-map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 \
-c:v libx264 -crf 22 -c:a aac -ar 48000 \
-filter:v:0 scale=w=480:h=360  -maxrate:v:0 600k -b:a:0 64k \
-filter:v:1 scale=w=640:h=480  -maxrate:v:1 900k -b:a:1 128k \
-filter:v:2 scale=w=1280:h=720 -maxrate:v:2 900k -b:a:2 128k \
-var_stream_map "v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p" \
-preset slow -hls_list_size 0 -threads 0 -f hls -hls_playlist_type event -hls_time 10 \
-hls_flags independent_segments -master_pl_name "master.m3u8" \
-y playlist-%v.m3u8

And it works also with exec.Command

...
args = []string{"-i", "source.mp4", "-y", "-map", "0:v:0", "-map", "0:a:0", "-map", "0:v:0", "-map", "0:a:0", "-map", "0:v:0", "-map",
"0:a:0", "-c:v", "libx264", "-crf", "22", "-c:a", "aac", "-ar", "48000", "-filter:v:0", "scale=w=480:h=360", "-maxrate:v:0", "600k",
"-b:a:0", "64k", "-filter:v:1", "scale=w=640:h=480", "-maxrate:v:1", "900k", "-b:a:1", "128k", "-filter:v:2", "scale=w=1280:h=720",
"-maxrate:v:2", "900k", "-b:a:2", "128k", "-var_stream_map", "v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p", "-preset", "slow",
"-hls_list_size", "0", "-threads", "0", "-f", "hls", "-hls_playlist_type", "event", "-hls_time", "10", "-hls_flags",
"independent_segments", "-master_pl_name", "master.m3u8", "playlist-%v.m3u8"}
cmd = exec.Command("ffmpeg", args...)
cmd.Dir = "/path/to/video/"

if err = cmd.Run(); err != nil {
 fmt.Println(err.Error())
return
}
...

As you can see, there are multiple -map arguments within the command with -var_stream_map argument. My question is, how achieve it with ffmpeg-go? Thanks in advance

Kirari04 commented 1 year ago

check ffmpeg_test.go, will TestCombinedOutput help?

func TestCombinedOutput(t *testing.T) {
  i1 := Input(TestInputFile1)
  i2 := Input(TestOverlayFile)
  out := Output([]*Stream{i1, i2}, TestOutputFile1)
  assert.Equal(t, []string{
      "-i",
      TestInputFile1,
      "-i",
      TestOverlayFile,
      "-map",
      "0",
      "-map",
      "1",
      TestOutputFile1,
  }, out.GetArgs())
}

Hi, great library! I'm trying to figure out how/whether multiple -map arguments are supported. E.g., in order to add artwork to a file, I'd do

ffmpeg -i "input_file.mp4" -i "Input_file.jpg" --map 1 -map 0  -acodec copy -vcodec copy "output_file.mp4"

(source: https://stackoverflow.com/a/53950948/4453524). However, KwArgs obviously complains that I use the -map key twice. Is there something I'm overlooking?

Similar question was asked in #1 and that solution might resolve your issue

frlrumahlogic commented 1 year ago

Hi @young-altair , have you found the solution? I'm working with similar use-case same as you.

aliworkshop commented 11 months ago

@young-altair I hope this code helps you ;)

mp4 := ffmpeg_go.Input("file.mp4", ffmpeg_go.KwArgs{ "hide_banner": "", "re": "", }).Output("%v/index.m3u8", ffmpeg_go.KwArgs{ "c:v": "h264", "profile:v": "main", "crf": 20, "sc_threshold": 0, "g": 48, "keyint_min": 48, "c:a": "aac", "ar": 48000, "filter:v:0": "scale=w=640:h=360", "maxrate:v:0": "856k", "bufsize:v:0": "1200k", "b:a:0": "96k", "filter:v:1": "scale=w=842:h=480", "maxrate:v:1": "1498k", "bufsize:v:1": "2100k", "b:a:1": "128k", "filter:v:2": "scale=w=1280:h=720", "maxrate:v:2": "2996k", "bufsize:v:2": "4200k", "b:a:2": "128k", "filter:v:3": "scale=w=1920:h=1080", "maxrate:v:3": "5350k", "bufsize:v:3": "7500k", "b:a:3": "192k", }, ffmpeg_go.KwArgs{"map": "0:v"}, ffmpeg_go.KwArgs{"map": "0:a"}, ffmpeg_go.KwArgs{"map": "0:v"}, ffmpeg_go.KwArgs{"map": "0:a"}, ffmpeg_go.KwArgs{"map": "0:v"}, ffmpeg_go.KwArgs{"map": "0:a"}, ffmpeg_go.KwArgs{"map": "0:v"}, ffmpeg_go.KwArgs{"map": "0:a"}, ffmpeg_go.KwArgs{"var_stream_map": "\"v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p v:3,a:3,name:1080p\""}, ffmpeg_go.KwArgs{"preset": "slow", "hls_list_size": 0, "threads": 0, "f": "hls", "hls_playlist_type": "vod", "hls_time": 4, "master_pl_name": "master.m3u8", "hls_segment_filename": "%v/%03d.ts"})

wenweiye commented 4 months ago

@young-altair I hope this code helps you ;)

mp4 := ffmpeg_go.Input("file.mp4", ffmpeg_go.KwArgs{ "hide_banner": "", "re": "", }).Output("%v/index.m3u8", ffmpeg_go.KwArgs{ "c:v": "h264", "profile:v": "main", "crf": 20, "sc_threshold": 0, "g": 48, "keyint_min": 48, "c:a": "aac", "ar": 48000, "filter:v:0": "scale=w=640:h=360", "maxrate:v:0": "856k", "bufsize:v:0": "1200k", "b:a:0": "96k", "filter:v:1": "scale=w=842:h=480", "maxrate:v:1": "1498k", "bufsize:v:1": "2100k", "b:a:1": "128k", "filter:v:2": "scale=w=1280:h=720", "maxrate:v:2": "2996k", "bufsize:v:2": "4200k", "b:a:2": "128k", "filter:v:3": "scale=w=1920:h=1080", "maxrate:v:3": "5350k", "bufsize:v:3": "7500k", "b:a:3": "192k", }, ffmpeg_go.KwArgs{"map": "0:v"}, ffmpeg_go.KwArgs{"map": "0:a"}, ffmpeg_go.KwArgs{"map": "0:v"}, ffmpeg_go.KwArgs{"map": "0:a"}, ffmpeg_go.KwArgs{"map": "0:v"}, ffmpeg_go.KwArgs{"map": "0:a"}, ffmpeg_go.KwArgs{"map": "0:v"}, ffmpeg_go.KwArgs{"map": "0:a"}, ffmpeg_go.KwArgs{"var_stream_map": "\"v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p v:3,a:3,name:1080p\""}, ffmpeg_go.KwArgs{"preset": "slow", "hls_list_size": 0, "threads": 0, "f": "hls", "hls_playlist_type": "vod", "hls_time": 4, "master_pl_name": "master.m3u8", "hls_segment_filename": "%v/%03d.ts"})

I have tried, keep one for the same key