我有一个AVI 电影文件(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, start: 0.000000, bitrate: 416 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1024x576 [SAR 1:1 DAR 16:9], 414 kb/s, 25 fps, 25 tbr, 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, start: 0.000000, bitrate: 383 kb/s
Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 720x576, 357 kb/s, 25 fps, 25 tbr, 12800 tbn, 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.getImageWidth(), 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();
}
}
}