微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用javacv将AVI文件导出到碎片mp4时如何获得正确的sample_aspect_ratio和display_aspect_ratio

如何解决使用javacv将AVI文件导出到碎片mp4时如何获得正确的sample_aspect_ratio和display_aspect_ratio

我有一个 AVI movie file(h264 编码),我想使用 JavaCV 将其导出为一个碎片化的 MP4 文件。从 ffprobe 命令的输出可以看出,此电影文件显示纵横比与样本纵横比不同:

ffprobe -show_streams Bureau.avi

导致(为简洁起见显示部分结果)

.
. 
 Duration: 00:00:31.00,start: 0.000000,bitrate: 1014 kb/s
    Stream #0:0: Video: h264 (High) (H264 / 0x34363248),yuv420p(progressive),720x576 [SAR 4320:3037 DAR 5400:3037],1010 kb/s,25 fps,25 tbr,25 tbn,50 tbc
.
.
sample_aspect_ratio=4320:3037
display_aspect_ratio=5400:3037
.
.

使用 ffmpeg 命令转换此视频文件

ffmpeg -i Bureau.avi -vf scale='trunc(ih*dar):ih',setsar=1/1 -frag_duration 1 -movflags empty_moov+default_base_moof+frag_keyframe Bureau_scaled_fragmented.mp4

mp4 文件的 ffprobe 结果是(为简洁起见,部分输出

.
.
Duration: 00:00:31.00,bitrate: 416 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661),yuv420p,1024x576 [SAR 1:1 DAR 16:9],414 kb/s,12800 tbn,50 tbc (default)
.
.
sample_aspect_ratio=1:1
display_aspect_ratio=16:9
.
.

使用 VLC 播放此视频文件时,视频的纵横比正确。

我希望能够通过使用 JavaCV 库(当前使用版本 1.5.5,但使用以下小型 Java 程序未成功,在该程序中我尝试使用 FfmpegFrameFilter 按原样缩放每个帧)被抓取。该程序确实导致生成一个mp4文件,但使用例如VLC播放时视频的纵横比不正确。ffprobe命令的结果还显示缺少SAR和DAR:

  Duration: 00:00:31.00,bitrate: 383 kb/s
    Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661),720x576,357 kb/s,25600 tbc (default)
.
.
sample_aspect_ratio=N/A
display_aspect_ratio=N/A
.
.

是否可以使用这样的帧过滤器(或通过任何其他方式)来缩放视频,以便产生的 sample_aspect_ratio 和 display_aspect_ratio 与使用 ffmpeg 命令时相同?

正在使用的 Java 程序。

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameFilter;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class App {


    public static void main(String[] args) throws IOException {
        File file = new File("/Users/werk/projects/video/bureau.avi");
        FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(file.getAbsolutePath());
        String fileName = null;
        Frame captured_frame = null;
        FFmpegFrameRecorder recorder = null;

        try {
            frameGrabber.start();
            fileName = file.getAbsolutePath().replace(".avi","_edited.mp4");
            recorder = new FFmpegFrameRecorder(fileName,frameGrabber.getimageWidth(),frameGrabber.getimageHeight(),frameGrabber.getAudioChannels());
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setVideoCodecName("avc");
            recorder.setFormat("mp4");
            // enable fragmented mp4 generation
            Map<String,String> options = new HashMap<>();
            options.put("frag_duration","1");
            options.put("movflags","empty_moov+default_base_moof+frag_keyframe");
            recorder.setoptions(options);

            recorder.setFrameRate(frameGrabber.getFrameRate());

            FFmpegFrameFilter filter = new FFmpegFrameFilter("scale='trunc(ih*dar):ih',setsar=1/1",frameGrabber.getimageHeight());
            filter.start();

            recorder.start();
            while (true) {
                try {
                    captured_frame = frameGrabber.grabFrame();

                    if (captured_frame == null) {
                        break;
                    }

                    filter.push(captured_frame);
                    Frame scaledFrame = filter.pull();
                    recorder.record(scaledFrame);

                } catch (Exception e) {
                    e.printstacktrace();
                }
            }
            recorder.stop();
            recorder.release();
            frameGrabber.stop();
            filter.stop();
        } catch (Exception e) {
            e.printstacktrace();
        }
    }

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。