I'm always impressed how smart FFmpeg has been designed so giving this a go. Can I use FFmpeg to convert part of a file to a compressed video file w/audio? The file I have consists of YUV420 frames interleaved with (floating point) audio PCM. So raw video & audio. I would like to convert part of it, so would want to give an offset into the file. It is part of a ring buffer so the file is opened and growing, but I have full control over this.
-
All raw demuxers expect a single stream. Can you deinterleave it yourself?– GyanCommented Apr 28, 2019 at 14:45
-
@Gyan Ah, I was hoping to avoid this as resource usage is at a premium. De-interleave to file or memory would not be my first choice. First time FFmpeg lets me down! If this is not possible I probably prefer to first look into some container format that supports the interleaved raw data, I can then copy it and slap a header in front of it. If something like that exists. It would not be compressed, but at least it can be exported.– Mike VersteegCommented Apr 28, 2019 at 18:13
-
what's the interleaving interval in bytes?– GyanCommented Apr 28, 2019 at 18:31
-
@Gyan It's VAVA.. The interval depends on the video resolution, e.g. a typical video frame would be 1382400 bytes, followed by 7680 bytes of audio. Repeat.– Mike VersteegCommented Apr 28, 2019 at 18:46
-
I may be able to do something about this. Give me a day or two.– GyanCommented Apr 28, 2019 at 19:18
1 Answer
Here's a method that should, in principle, work. It assumes VAVA interleaving and for somewhat efficient processing requires the packet sizes for both video and audio having a reasonably large greatest common divisor.
The examples below assume a video packet size of 1382400
bytes and audio of 7680
bytes. As it happens, the former is exactly 180 times the latter. The idea is we can ingest the raw stream as a raw "audio" stream and deinterleave using a selection expression, which routes 180 "frames" to one output and the 181st frame to another. Then the separated outputs are dumped into regular or fifo files which can then be read by another ffmpeg process with a sane interpretation of the input.
Command 1:
ffmpeg -f u8 -channels 1 -i raw-input-url -filter_complex "asetnsamples=7680,aselect='1+not(mod(n+1,181))':n=2[vid][aud]" -map [vid] -f u8 file-vid -map [aud] -f u8 file-aud
Command 1 with input offset:
ffmpeg -f u8 -channels 1 -i "subfile,,start,3248615,end,0,,:raw-input-url" -filter_complex "asetnsamples=7680,aselect='1+not(mod(n+1,181))':n=2[vid][aud]" -map [vid] -f u8 file-vid -map [aud] -f u8 file-aud
where 3248615
is in bytes and should point to the start of a video frame for this to work.
Command 2:
ffmpeg -f rawvideo -pixel_format yuv420p -framerate F -video_size WxH -i file-vid -f f32le -channels N -sample_rate R -i file-aud { -encoding parameters } output
-
Thanks Gyan. Weird as SE did not notify me of this answer. I'll let you know how it turns out. Commented Apr 30, 2019 at 15:04
-
I am thoroughly impressed. Except for a required vflip this worked the first time. Thanks! Commented May 6, 2019 at 13:14