Hello everyone!
I'm trying to make Android app that opens the video using FFmpegFrameGrabber does some processing using opencv and then saves the result in new video using FFmpegFrameRecorder.
Whenever I'm trying to write video to file I get the following exception - avformat_write_header error() error -22: Could not write header to 'null'
I've been able to replicate the error on linux with this code:
InputStream is = new FileInputStream(args[0]);
OutputStream os = new FileOutputStream("DEMO.mp4");
frameGrabber = new FFmpegFrameGrabber(is);
frameRecorder = new FFmpegFrameRecorder(os, frameGrabber.getAudioChannels());
frameGrabber.setFormat("mp4");
frameRecorder.setFormat("mp4");
frameGrabber.start();
frameRecorder.start();
while (true){
frame = frameGrabber.grabFrame();
if(frame == null){
break;
}
frameRecorder.record(frame);
}
frameGrabber.stop();
frameRecorder.stop();
frameGrabber.close();
frameRecorder.close();
is.close();
os.close();
which creates empty file and gives me this output in terminal
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'java.io.BufferedInputStream@5cdd8682':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2019-11-17T10:17:15.000000Z
Duration: 00:00:14.54, start: 0.000000, bitrate: 2414 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1080x1920 [SAR 1:1 DAR 9:16], 2321 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
creation_time : 2019-11-17T12:46:20.000000Z
handler_name : ISO Media file produced by Google Inc. Created on: 11/17/2019.
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
creation_time : 2019-11-17T12:46:20.000000Z
handler_name : ISO Media file produced by Google Inc. Created on: 11/17/2019.
[mp4 @ 0x7f5224bfaf80] No streams to mux were specified
org.bytedeco.javacv.FrameRecorder$Exception: avformat_write_header error() error -22: Could not write header to 'null'
thanks for help
I don't think the mp4 format supports audio streams without video streams.
Try the aac format if that's what you're looking to do.
At this point I'm just basically trying to "copy" the video into new file. I've tried to change frame recorder initialization to this
frameGrabber = new FFmpegFrameGrabber(is);
frameRecorder = new FFmpegFrameRecorder("DEMO.mp4", frameGrabber.getImageWidth(), frameGrabber.getImageHeight());
frameGrabber.setFormat("mp4");
frameRecorder.setFormat("mp4");
frameRecorder.setVideoCodec(frameGrabber.getVideoCodec());
frameRecorder.setAudioCodec(avcodec.AV_CODEC_ID_H264);
frameRecorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
frameRecorder.setFrameRate(frameGrabber.getFrameRate());
And use sample mp4 video from sample-videos.com with exactly the same results as before
The end result of what I'm trying to achieve is on android let user select video file extract video frames, modify them using opencv and then save result as new video which can then be played using androids Videoview
In that case, you'll need to set both the image size and the number of channels, something like this:
frameRecorder = new FFmpegFrameRecorder("DEMO.mp4", frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), frameGrabber.getAudioChannels());
I did, recorder still throws avformat_write_header error() error -22 : could not write header to 'null' exception when calling start method. This is my current code
InputStream is = new FileInputStream(args[0]);
frameGrabber = new FFmpegFrameGrabber(is);
frameRecorder = new FFmpegFrameRecorder("DEMO.mp4",
frameGrabber.getImageWidth(),
frameGrabber.getImageHeight(),
frameGrabber.getAudioChannels());
frameGrabber.setFormat("mp4");
frameRecorder.setFormat("mp4");
frameGrabber.start();
frameRecorder.start();
And the log?
this is the terminal output
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'java.io.BufferedInputStream@5cdd8682':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isommp42
creation_time : 2019-11-17T10:17:15.000000Z
Duration: 00:00:14.54, start: 0.000000, bitrate: 2414 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709/bt709/smpte170m), 1080x1920 [SAR 1:1 DAR 9:16], 2321 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
creation_time : 2019-11-17T12:46:20.000000Z
handler_name : ISO Media file produced by Google Inc. Created on: 11/17/2019.
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
creation_time : 2019-11-17T12:46:20.000000Z
handler_name : ISO Media file produced by Google Inc. Created on: 11/17/2019.
[mp4 @ 0x7f651cf25e40] No streams to mux were specified
org.bytedeco.javacv.FrameRecorder$Exception: avformat_write_header error() error -22: Could not write header to 'null'
That works just fine here... Maybe it's a problem with file permissions or something.
Found the issue!!!
Basically the problem was initializing frame recorder before calling start method of frame grabber
yes,you must start FFmpegFrameGrabber before initializing FFmpegFrameRecorder.
ex:
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(input);
grabber.start();
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
output,grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
recorder.start();
Most helpful comment
Found the issue!!!
Basically the problem was initializing frame recorder before calling start method of frame grabber