0

I have an integration with an API that sends us an FLV with an H.264 codec. I use FFMpeg (FFMpegCore, a C# library that interacts with FFMpeg) to convert the container to a fragmented MP4 container. The result is then streamed to resp.OutputStream, and the file's downloaded.

However, the result contains no stream duration and Windows Media Player is unable to navigate the file.

The stream is handled via the following code:

FFMpegArguments
.FromPipe(new StreamPipeSource(inputStream))
.WithVideoCodec("copy")
.ForceFormat("mp4")
.WithArgument(new FragArgument())
.OutputToPipe(new StreamPipeSink(resp.OutputStream))
.ProcessSynchronously(false);

Which roughly equates to the following command:

type "Input.flv" | ffmpeg -i - -vcodec copy -f mp4 -movflags frag_keyframe+empty_moov pipe:1 > Output.mp4

(FragArgument is something I created myself which simply adds -movflags frag_keyframe+empty_moov to the command)

The outputted stream has a duration of 0. Media players such as VLC seem to be able to calculate the durations, but the client is unable to use VLC media player, instead having to use Windows Media Player, which is able to play the file but does not properly record the duration.

I'm quite new to handling video streams, but the lack of a duration seems to be something the muxer does, according to this stack overflow answer

I think I can get a stream duration if I output as a non-fragmented mp4 to a local file, then stream that to the server. However, the extra step would increase the download time, and I would have to worry about deleting the file afterwards, which I am trying to avoid doing.

How do I get my stream to include the correct durations without first saving to a file?

Max Hay
  • 230
  • 2
  • 11
  • It sounds like your problem could be caused by the moov atom being at the end. Could you try adding `.WithFastStart()` to let ffmpeg move it to the beginning? – Malte R Oct 16 '20 at 15:35
  • I will try that on Monday, which is when I will next be able to. – Max Hay Oct 16 '20 at 16:15
  • I tried it this morning - the download ended up being 0kb so I suspect it failed silently for some reason. I'll do some debugging later when I get a chance. – Max Hay Oct 19 '20 at 09:29
  • Does it work when using the ffmpeg command args directly in a terminal? – Malte R Oct 31 '20 at 03:27
  • 1
    Good question. I just tried using:`type "input.flv" | ffmpeg -i - -vcodec copy -f mp4 -movflags frag_keyframe+empty_moov+faststart pipe:1 > Output.mp4` No dice, the result is the same as before, with no stream duration. Though I know why the `FFMpegCore.WithFastStart()` failed now - it would have been appending 2 `-movflag` arguments – Max Hay Nov 02 '20 at 12:36
  • If the command doesn't work with ffmpeg direcetly, I wouldn't expect it to work with FFMpegCore. Why to you need the pipe:1 arg? – Malte R Nov 02 '20 at 19:00
  • The server itself has to use pipes to retrieve the stream, I think, so the pipe arg's there just to emulate the same effect. You'll notice that if you remove the pipe args and remove frag_keyframe then the you can achieve the desired affect that I'm looking for, but if you keep the pipe you recieve a `muxer does not support non seekable output` error – Max Hay Nov 03 '20 at 15:26
  • Okay, it seems reasonable that seeking isn't possible since you only creating the stream just-in-time, so seeking forwards would seek into content that hasn't transcoded yet. If you want it seekable, I think you will have to transcode the entire stream, save it somewhere, and serve it with range request support – Malte R Nov 05 '20 at 14:54
  • I think you're probably right to be honest. I will leave the question open, though, just in case. Thanks for all your help. – Max Hay Nov 05 '20 at 16:13

0 Answers0