livepeer / lpms

Livepeer media server
MIT License
285 stars 72 forks source link

implement looping, demuxer options #420

Open iameli-streams opened 3 months ago

iameli-streams commented 3 months ago

So -stream_loop doesn't work when provided as a demuxer option, as it's implemented in https://github.com/FFmpeg/FFMpeg/blob/master/fftools/ffmpeg_demux.c and we handle our own demuxing. Thankfully, this seemed to be relatively easy to port over using the preexisting work that we have for handling discontinuity. Lightly tested.

Demuxer options: Pretty straightforward, follows the same syntax as the output muxer options.

My use case: I've already got a livestream being sliced up into a bunch of C2PA-signed MP4 files. But now I need to turn them back into an MKV stream. To do this I'm using a hack on top of ffmpeg's concat muxer, looks like this on the command line:

ffmpeg \
  -stream_loop -1 \
  -safe 0 \
  -protocol_whitelist file,http,https,tcp,tls \
  -i http://127.0.0.1:9090/playback/0xf081d6383777482868faa8d5534a5f1a7777bee8/concat \
  -map 0 \
  -c copy \
  -y output.mkv

And that concat file looks like this:

ffconcat version 1.0
file 'http://127.0.0.1:9090/playback/0xf081d6383777482868faa8d5534a5f1a7777bee8/latest.mp4'
file 'http://127.0.0.1:9090/playback/0xf081d6383777482868faa8d5534a5f1a7777bee8/latest.mp4'

And those latest.mp4 files get 301 redirected to the correct MP4 files. Works great!

j0sh commented 3 months ago

I love to see improvements like this, thanks @iameli !

The demuxer changes LGTM, it might be nice to have a test case exercising that. One scenario where I think it would be needed to specify the demuxer is for m3u8 files that don't have a standard extension - see the ffmpeg code (hit this during the ffmpeg 7 upgrade; see the diff for the TestTranscoder_FomatOptions testcase)

The looping changes look good too but I am curious how it would behave with non-seekable inputs like most non-HTTP network protocols, pipes, etc. Other than that it would be nice to have tests for those too: check that the output is as expected etc for both seekable and non-seekable inputs. For non-seekable it would still be good to codify the behavior even if it is explicitly not supported.

iameli-streams commented 3 months ago

Thanks for taking a look @j0sh!

I'm having trouble getting that test working, I've tried a couple environments...

root@e230e4d291c9:/home/iameli/code/lpms# go test -coverprofile cover.out -run ^TestTranscoder_FormatOptions$ ./ffmpeg/... 2>&1 | tee test.log
?       github.com/livepeer/lpms/ffmpeg/proto   [no test files]
ERROR: encoder.c:220] Unable to guess output format : Invalid argument
ERROR: transcoder.c:238] Unable to open output : Invalid argument
E0831 12:15:07.179209   37135 ffmpeg.go:1015] Transcoder Return : Invalid argument
--- FAIL: TestTranscoder_FormatOptions (0.51s)
    ffmpeg_test.go:1637: Invalid argument
    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_format test.flv
        + grep format_name=flv
        test.flv: No such file or directory

    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mpegts.flv
        + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mp4.flv
        + cat
        + diff -u actually_mpegts.out test.out
        + diff -u actually_mp4.out expected_mp4.out
        --- actually_mp4.out    2024-08-31 12:15:07.459846342 -0700
        +++ expected_mp4.out    2024-08-31 12:15:07.463846331 -0700
        @@ -1,4 +1,4 @@
         [FORMAT]
         format_name=mov,mp4,m4a,3gp,3g2,mj2
        -duration=8.033000
        +duration=8.032667
         [/FORMAT]

    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mpegts_2.flv
        + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mp4_2.flv
        + diff -u actually_mpegts_2.out test.out
        + diff -u actually_mp4_2.out expected_mp4.out
        --- actually_mp4_2.out  2024-08-31 12:15:07.570846055 -0700
        +++ expected_mp4.out    2024-08-31 12:15:07.463846331 -0700
        @@ -1,4 +1,4 @@
         [FORMAT]
         format_name=mov,mp4,m4a,3gp,3g2,mj2
        -duration=8.033000
        +duration=8.032667
         [/FORMAT]

FAIL
    github.com/livepeer/lpms/ffmpeg coverage: 39.3% of statements
FAIL    github.com/livepeer/lpms/ffmpeg 0.520s
FAIL
root@e230e4d291c9:/home/iameli/code/lpms# cat test.log 
?       github.com/livepeer/lpms/ffmpeg/proto   [no test files]
ERROR: encoder.c:220] Unable to guess output format : Invalid argument
ERROR: transcoder.c:238] Unable to open output : Invalid argument
E0831 12:15:07.179209   37135 ffmpeg.go:1015] Transcoder Return : Invalid argument
--- FAIL: TestTranscoder_FormatOptions (0.51s)
    ffmpeg_test.go:1637: Invalid argument
    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_format test.flv
        + grep format_name=flv
        test.flv: No such file or directory

    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mpegts.flv
        + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mp4.flv
        + cat
        + diff -u actually_mpegts.out test.out
        + diff -u actually_mp4.out expected_mp4.out
        --- actually_mp4.out    2024-08-31 12:15:07.459846342 -0700
        +++ expected_mp4.out    2024-08-31 12:15:07.463846331 -0700
        @@ -1,4 +1,4 @@
         [FORMAT]
         format_name=mov,mp4,m4a,3gp,3g2,mj2
        -duration=8.033000
        +duration=8.032667
         [/FORMAT]

    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mpegts_2.flv
        + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mp4_2.flv
        + diff -u actually_mpegts_2.out test.out
        + diff -u actually_mp4_2.out expected_mp4.out
        --- actually_mp4_2.out  2024-08-31 12:15:07.570846055 -0700
        +++ expected_mp4.out    2024-08-31 12:15:07.463846331 -0700
        @@ -1,4 +1,4 @@
         [FORMAT]
         format_name=mov,mp4,m4a,3gp,3g2,mj2
        -duration=8.033000
        +duration=8.032667
         [/FORMAT]

FAIL
    github.com/livepeer/lpms/ffmpeg coverage: 39.3% of statements
FAIL    github.com/livepeer/lpms/ffmpeg 0.520s
FAIL
root@e230e4d291c9:/home/iameli/code/lpms#
j0sh commented 3 months ago

Is this the most recent ffmpeg build / debug executable from install_ffmpeg.sh ? The 7.0 upgrade resulted in a bunch of timestamp adjustments to the CLI output and this looks like what the old version had

On Sat, Aug 31, 2024 at 12:15 PM iameli-streams @.***> wrote:

Thanks for taking a look @j0sh https://github.com/j0sh!

I'm having trouble getting that test working, I've tried a couple environments...

@.***:/home/iameli/code/lpms# go test -coverprofile cover.out -run ^TestTranscoder_FormatOptions$ ./ffmpeg/... 2>&1 | tee test.log ? github.com/livepeer/lpms/ffmpeg/proto [no test files] ERROR: encoder.c:220] Unable to guess output format : Invalid argument ERROR: transcoder.c:238] Unable to open output : Invalid argument E0831 12:15:07.179209 37135 ffmpeg.go:1015] Transcoder Return : Invalid argument --- FAIL: TestTranscoder_FormatOptions (0.51s) ffmpeg_test.go:1637: Invalid argument ffmpeg_test.go:35: + ffprobe -loglevel warning -show_format test.flv

  • grep format_name=flv test.flv: No such file or directory

    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mpegts.flv

  • ffprobe -loglevel warning -show_entries format=format_name,duration actually_mp4.flv
  • cat
  • diff -u actually_mpegts.out test.out
  • diff -u actually_mp4.out expected_mp4.out --- actually_mp4.out 2024-08-31 12:15:07.459846342 -0700 +++ expected_mp4.out 2024-08-31 12:15:07.463846331 -0700 @@ -1,4 +1,4 @@ [FORMAT] format_name=mov,mp4,m4a,3gp,3g2,mj2 -duration=8.033000 +duration=8.032667 [/FORMAT]

    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mpegts_2.flv

  • ffprobe -loglevel warning -show_entries format=format_name,duration actually_mp4_2.flv
  • diff -u actually_mpegts_2.out test.out
  • diff -u actually_mp4_2.out expected_mp4.out --- actually_mp4_2.out 2024-08-31 12:15:07.570846055 -0700 +++ expected_mp4.out 2024-08-31 12:15:07.463846331 -0700 @@ -1,4 +1,4 @@ [FORMAT] format_name=mov,mp4,m4a,3gp,3g2,mj2 -duration=8.033000 +duration=8.032667 [/FORMAT]

FAIL github.com/livepeer/lpms/ffmpeg coverage: 39.3% of statements FAIL github.com/livepeer/lpms/ffmpeg 0.520s FAIL @.***:/home/iameli/code/lpms# cat test.log ? github.com/livepeer/lpms/ffmpeg/proto [no test files] ERROR: encoder.c:220] Unable to guess output format : Invalid argument ERROR: transcoder.c:238] Unable to open output : Invalid argument E0831 12:15:07.179209 37135 ffmpeg.go:1015] Transcoder Return : Invalid argument --- FAIL: TestTranscoder_FormatOptions (0.51s) ffmpeg_test.go:1637: Invalid argument ffmpeg_test.go:35: + ffprobe -loglevel warning -show_format test.flv

  • grep format_name=flv test.flv: No such file or directory

    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mpegts.flv

  • ffprobe -loglevel warning -show_entries format=format_name,duration actually_mp4.flv
  • cat
  • diff -u actually_mpegts.out test.out
  • diff -u actually_mp4.out expected_mp4.out --- actually_mp4.out 2024-08-31 12:15:07.459846342 -0700 +++ expected_mp4.out 2024-08-31 12:15:07.463846331 -0700 @@ -1,4 +1,4 @@ [FORMAT] format_name=mov,mp4,m4a,3gp,3g2,mj2 -duration=8.033000 +duration=8.032667 [/FORMAT]

    ffmpeg_test.go:35: + ffprobe -loglevel warning -show_entries format=format_name,duration actually_mpegts_2.flv

  • ffprobe -loglevel warning -show_entries format=format_name,duration actually_mp4_2.flv
  • diff -u actually_mpegts_2.out test.out
  • diff -u actually_mp4_2.out expected_mp4.out --- actually_mp4_2.out 2024-08-31 12:15:07.570846055 -0700 +++ expected_mp4.out 2024-08-31 12:15:07.463846331 -0700 @@ -1,4 +1,4 @@ [FORMAT] format_name=mov,mp4,m4a,3gp,3g2,mj2 -duration=8.033000 +duration=8.032667 [/FORMAT]

FAIL github.com/livepeer/lpms/ffmpeg coverage: 39.3% of statements FAIL github.com/livepeer/lpms/ffmpeg 0.520s FAIL @.***:/home/iameli/code/lpms#

— Reply to this email directly, view it on GitHub https://github.com/livepeer/lpms/pull/420#issuecomment-2323020913, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACHNHR4MBZXAVBHI5WXGDDZUII6VAVCNFSM6AAAAABNJDA5TWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMRTGAZDAOJRGM . You are receiving this because you were mentioned.Message ID: @.***>