Is it possible to read incomplete FFmpegFrameRecorder files

221 views
Skip to first unread message

Sam West

unread,
Mar 12, 2015, 10:16:51 PM3/12/15
to jav...@googlegroups.com
Hi,

First of all, thanks to Samuel Audet for creating and maintaining a killer set of libraries for us to play with :)

And my question: I'm running some code that takes a long time to complete, and it would be really useful to be able to view the MP4 file created by FFmpegFrameRecorder before the application calls stops on the recorder, to make sure everything is working ok (I'm running a few hundred processes in parallel on a cluster to process a large dataset, and don't want to wait a few days to find that it didn't work).

So I guess my question is, can FFmpegFrameRecorder be set up so that the file on disk can be read by a video player before rec.stop()is called?

I think this is similar to the faststart progressive encoding switch mentioned in posts here and here and the ffmpeg wiki, which I've added, but it doesn't seem to work. 
My files seem to have the MP4 header (a block with moovmvhd, trak strings etc) at the end regardless of whether I ass the faststart switches as in my the code below.


final FFmpegFrameRecorder rec = new FFmpegFrameRecorder(file, width, height);
rec.setVideoCodec(avcodec.AV_CODEC_ID_H264);
rec.setFormat("mp4"); 
rec.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); 
rec.setVideoQuality(20); //0=lossless, 23=pretty good
rec.setGopSize(10); //key-frame interval
rec.setFrameRate(frameRate);
rec.setVideoOption("faststart", "1"); //put header at start of file so incomplete movies will still play. Not sure if this works.
rec.setVideoOption("movflags", "+faststart"); 
rec.setVideoOption("movflags", "faststart");
rec.start();
//encode frames...
rec.stop()
rec.release()

Has anyone been able to get progressive encoding to work, and would this let me play my incomplete MP4 files?

Cheers,
Sam.

Samuel Audet

unread,
Mar 15, 2015, 8:47:07 AM3/15/15
to jav...@googlegroups.com
On 03/13/2015 10:05 AM, Sam West wrote:
Hi,

First of all, thanks to Samuel Audet for creating and maintaining a killer set of libraries for us to play with :)
Sure, I'm happy to provide something that no one else is :) If you ever feel like making a contribution, it would be most welcome.


And my question: I'm running some code that takes a long time to complete, and it would be really useful to be able to view the MP4 file created by FFmpegFrameRecorder before the application calls stops on the recorder, to make sure everything is working ok (I'm running a few hundred processes in parallel on a cluster to process a large dataset, and don't want to wait a few days to find that it didn't work).
I believe that would be most feasible if we add support for InputStream and OutputStream. Is this the case? That's something a few people have already expressed an interest in having:
    Add a new API to FFmpegFrameGrabber/Recorder to take a stream as input parameter #95


So I guess my question is, can FFmpegFrameRecorder be set up so that the file on disk can be read by a video player before rec.stop()is called?
That would depend on the capabilities of the file format, and what the underlying OS lets us do. But I don't see any reason to do that if we can do everything inside Java with streams before it hits the disk though.


I think this is similar to the faststart progressive encoding switch mentioned in posts here and here and the ffmpeg wiki, which I've added, but it doesn't seem to work.
I'm not sure I see the parallel...


My files seem to have the MP4 header (a block with moovmvhd, trak strings etc) at the end regardless of whether I ass the faststart switches as in my the code below.
AFAIK, that's a format option, not a codec option, so we'd need to add something like a FFmpegFrameRecorder.setFormatOption() method to be able to set that.

final FFmpegFrameRecorder rec = new FFmpegFrameRecorder(file, width, height);
rec.setVideoCodec(avcodec.AV_CODEC_ID_H264);
rec.setFormat("mp4"); 
rec.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); 
rec.setVideoQuality(20); //0=lossless, 23=pretty good
rec.setGopSize(10); //key-frame interval
rec.setFrameRate(frameRate);
rec.setVideoOption("faststart", "1"); //put header at start of file so incomplete movies will still play. Not sure if this works.
rec.setVideoOption("movflags", "+faststart"); 
rec.setVideoOption("movflags", "faststart");
rec.start();
//encode frames...
rec.stop()
rec.release()

Has anyone been able to get progressive encoding to work, and would this let me play my incomplete MP4 files?
According to FFmpeg's documentation, "faststart" merely moves all metadata to the header, after all encoding is done. So I don't believe this is what you are looking for. There's most likely other options relevant for streaming video, but this isn't one of them.

Samuel

Sam West

unread,
Mar 18, 2015, 12:30:03 AM3/18/15
to jav...@googlegroups.com
Hi Samuel, 

Thanks for responding :)

Java stream support would probably help do this programmatically, if this would let me view an ongoing encoding session via a video stream over http or something.
I was thinking that it'd be useful to be able to open an incomplete video file from disk before the encoding process had actually completed though, and skip forward/backwards so I can do spot checks to make sure my code is working properly.

The good news is that I figured out how to achieve this! 

The answer was to change container format from MP4 to MKV, which seems to support playing of incomplete files better!

So now, if I set up an encoder as below, I can open the file in VLC player or MPC-HC while encoding is still happening. You have to wait until after the 25th frame for some reason (regardless of the framerate and GOP settings), but it works well otherwise.

 final FFmpegFrameRecorder rec = new FFmpegFrameRecorder(file, width, height);
 rec
.setVideoCodec(avcodec.AV_CODEC_ID_H264);
 rec.setFormat("mkv"); //This is the key!

 rec
.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
 rec
.setVideoQuality(20); //0=lossless, 23=pretty good
 rec
.setGopSize(10); //key-frame interval
 rec
.setFrameRate(frameRate);

Thanks for the help :)

Cheers,
Sam.

Samuel Audet

unread,
Mar 23, 2015, 7:46:55 AM3/23/15
to jav...@googlegroups.com
On 03/18/2015 01:30 PM, Sam West wrote:
rec.setFormat("mkv"); //This is the key!
For sure, if you have the possibility of using another container than MP4, that's an option.

MP4 is only really useful because Windows Media Player and QuickTime can play them without extensions. But when we don't need that, something like MKV is much better overall, yes.

Samuel
Reply all
Reply to author
Forward
0 new messages