bytedeco/javacv

the FFmpegFrameRecorder created video's quality is lower than originals

Open

#2,041 opened on Jun 13, 2023

View on GitHub
 (3 comments) (0 reactions) (0 assignees)Java (1,583 forks)batch import
help wantedquestion

Repository metrics

Stars
 (6,985 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

I am using FFmpegFrameGrabber to grab frame images from a video, and doing some image processing, then using FFmpegFrameRecorder to record frames to a new video file.

And, I find that the created new video's quality is lower than the original video. I have tryed to set the recorder as same as the grabber, however, it is still lower than expected.

Is there anything I could do to make the recorder to create video as the same quality, under same frame rate/bit rate.

Here is my code, only recording the frame grabbed `public static void copyVideo(String inputVideoFile, String outputVideoFile) throws FFmpegFrameGrabber.Exception, FFmpegFrameRecorder.Exception { FFmpegFrameGrabber videoGrabber = FFmpegFrameGrabber.createDefault(inputVideoFile); videoGrabber.start();

    FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputVideoFile, videoGrabber.getAudioChannels());
    recorder.setFrameRate(videoGrabber.getFrameRate());
    recorder.setVideoCodec(videoGrabber.getVideoCodec());
    recorder.setVideoBitrate(videoGrabber.getVideoBitrate());
    recorder.setImageHeight(videoGrabber.getImageHeight());
    recorder.setImageWidth(videoGrabber.getImageWidth());
    recorder.setFormat(videoGrabber.getFormat());
    recorder.setVideoOptions(videoGrabber.getVideoOptions());
    recorder.setVideoMetadata(videoGrabber.getVideoMetadata());
    recorder.setVideoQuality(1);
    recorder.setVideoOption("profile", "high");

    recorder.start();

    Frame frame = null;
    while ((frame = videoGrabber.grabImage()) != null) {
        recorder.record(frame);
    }

    recorder.stop();
    videoGrabber.stop();
}`

Here is one frame of the new video, captured by screen shot tool from video player out

Here is the original's, same way to get ori

Here is the ffmpeg output log

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'ori.mp4': Metadata: major_brand : isom minor_version : 512 encoder : Lavf58.29.100 Duration: 02:08:53.13, start: 0.000000, bitrate: 1841 kb/s Stream #0:00x1: Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 1705 kb/s, 29.97 fps, 29.97 tbr, 90k tbn (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] Stream #0:10x2: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default) Metadata: handler_name : SoundHandler vendor_id : [0][0][0][0] [libopenh264 @ 00000176fe8cb2c0] Slice count will be set automatically [libopenh264 @ 00000176fe8cb2c0] [OpenH264] this = 0x00000176fe8ce200, Warning:bEnableFrameSkip = 0,bitrate can't be controlled for RC_QUALITY_MODE,RC_BITRATE_MODE and RC_TIMESTAMP_MODE without enabling skip frame. Output #0, mp4, to 'out.mp4': Metadata: encoder : Lavf59.27.100 Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 1920x1080, q=2-31, 1705 kb/s, 29.97 fps, 30k tbn Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 64 kb/s

The differeces between input and output Input Stream #0:00x1: Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 1705 kb/s, 29.97 fps, 29.97 tbr, 90k tbn (default) Output Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 1920x1080, q=2-31, 1705 kb/s, 29.97 fps, 30k tbn

Contributor guide