ffmpeg:处理分辨率不断变化的视频

ffmpeg:处理分辨率不断变化的视频,ffmpeg,Ffmpeg,我编写了一个程序,以编程方式连接视频输入列表。问题在于,这些视频是录制流的一部分,它们的分辨率在同一文件中可能会发生几次变化。 目前,如果出现这种情况,ffmpeg将失败,表示无法使用不同的分辨率压缩文件。有没有办法让ffmpeg自动处理这个问题?一个好的解决方案是选择具有意外分辨率的帧缩放 以下是一份清单: ffmpeg -y -i 1.mkv -i 1.mka -max_muxing_queue_size 10000 -preset veryfast -r 30 -crf 20 -b:a 9

我编写了一个程序,以编程方式连接视频输入列表。问题在于,这些视频是录制流的一部分,它们的分辨率在同一文件中可能会发生几次变化。 目前,如果出现这种情况,ffmpeg将失败,表示无法使用不同的分辨率压缩文件。有没有办法让ffmpeg自动处理这个问题?一个好的解决方案是选择具有意外分辨率的帧缩放

以下是一份清单:

ffmpeg -y -i 1.mkv -i 1.mka
-max_muxing_queue_size 10000
-preset veryfast -r 30 -crf 20 -b:a 96000 -vbr on
-strict experimental
-filter_complex '
color=black:s=320x240:d=7ms[black0];
aevalsrc=0:d=15ms[silence1];
[black0][0]concat=n=2:v=1:a=0[video];
[1][silence1]concat=n=2:v=0:a=1[audio]'
-map [video] -map [audio] -c:v libvpx -c:a libopus output.webm

ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers
  built with Apple clang version 11.0.0 (clang-1100.0.33.17)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/4.3.1_9 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-videotoolbox --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack
  libavutil      56. 51.100 / 56. 51.100
  libavcodec     58. 91.100 / 58. 91.100
  libavformat    58. 45.100 / 58. 45.100
  libavdevice    58. 10.100 / 58. 10.100
  libavfilter     7. 85.100 /  7. 85.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  7.100 /  5.  7.100
  libswresample   3.  7.100 /  3.  7.100
  libpostproc    55.  7.100 / 55.  7.100
Input #0, matroska,webm, from '1.mkv':
  Metadata:
    encoder         : GStreamer matroskamux version 1.8.1.1
    creation_time   : 2021-03-02T13:44:03.000000Z
  Duration: 00:01:48.41, start: 0.710000, bitrate: 757 kb/s
    Stream #0:0(eng): Video: vp8, yuv420p(progressive), 320x240, SAR 1:1 DAR 4:3, 120 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      title           : Video
Input #1, matroska,webm, from '1.mka':
  Metadata:
    encoder         : GStreamer matroskamux version 1.8.1.1
    creation_time   : 2021-03-02T13:44:03.000000Z
  Duration: 00:01:48.40, start: 0.703000, bitrate: 38 kb/s
    Stream #1:0(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
    Metadata:
      title           : Audio
Codec AVOption preset (Configuration preset) specified for output file #0 (output.webm) has not been used for any stream. The most likely reason is either wrong type (e.g. a video option with no video streams) or that it is a private option of some encoder which was not actually used for any stream.
Stream mapping:
  Stream #0:0 (vp8) -> concat:in1:v0
  Stream #1:0 (opus) -> concat:in0:a0
  concat -> Stream #0:0 (libvpx)
  concat -> Stream #0:1 (libopus)
Press [q] to stop, [?] for help
[libvpx @ 0x7fe08a80bc00] v1.9.0
[libvpx @ 0x7fe08a80bc00] Bitrate not specified for constrained quality mode, using default of 256kbit/sec
Output #0, webm, to 'output.webm':
  Metadata:
    encoder         : Lavf58.45.100
    Stream #0:0: Video: vp8 (libvpx), yuv420p, 320x240 [SAR 1:1 DAR 4:3], q=-1--1, 256 kb/s, 30 fps, 1k tbn, 30 tbc (default)
    Metadata:
      encoder         : Lavc58.91.100 libvpx
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
    Stream #0:1: Audio: opus (libopus), 48000 Hz, stereo, flt, 96 kb/s (default)
    Metadata:
      encoder         : Lavc58.91.100 libopus
[Parsed_color_0 @ 0x7fe089815940] EOF timestamp not reliable
[Parsed_concat_2 @ 0x7fe088501980] Input link in0:v0 parameters (size 640x480, SAR 1:1) do not match the corresponding output link in0:v0 parameters (320x240, SAR 1:1)
[Parsed_concat_2 @ 0x7fe088501980] Failed to configure output pad on Parsed_concat_2
Error reinitializing filters!
Failed to inject frame into filter network: Invalid argument
Error while processing the decoded data for stream #0:0
[libopus @ 0x7fe08a810c00] 1 frames left in the queue on closing
Conversion failed!

这是唯一一个具有“浮动”分辨率的视频,它不能与320x240彩色滤光片连接。

如果我没有错,您只想合并具有不同分辨率的视频,那么这对您有效,请查看给定代码:

说明:在这里,我创建了
pad
(一种类型的容器),我在其中安装视频,这样每个视频都会自动适应给定的pad大小,如果您的任何视频处于静音状态,还有一件事将导致命令失败,因此我添加了新方法
isVideoHaveAudioTrack()
它检查视频是否有音频,如果视频没有音频,那么我们必须添加静音音频,以便out命令可以成功运行

private boolean isVideoHaveAudioTrack(String path) {

    boolean isAudioTrackAvailable;
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    try {
        retriever.setDataSource(path);
        String hasAudioStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
        isAudioTrackAvailable = hasAudioStr != null && hasAudioStr.equals("yes");
    } catch (Exception e) {
        isAudioTrackAvailable = false;
    }

    return isAudioTrackAvailable;
}


public static LinkedList<String> mergeVideo(ArrayList<Video> selectedVideos, String silencedAudio, String filepath) {

    String str3 = "";
    StringBuilder str4 = new StringBuilder(str3);
    StringBuilder str5 = new StringBuilder(str4.toString());

    boolean isAnyMuteVideo = false;

    LinkedList<String> commandList = new LinkedList<>();
    for (int i = 0; i < selectedVideos.size(); i++) {
        commandList.add("-i");
        commandList.add(selectedVideos.get(i).getLocation());
        if (!isVideoHaveAudioTrack(selectedVideos.get(i).getPath())) {
            isAnyMuteVideo = true;
        }
        if (i == selectedVideos.size() - 1) {
            if (isAnyMuteVideo) {
                commandList.add("-i");
                commandList.add(silencedAudio);
            }
        }

        String str6 = str3 + "[" + i + ":v]fps=25,scale=w=min(iw*" + "1280" + "/ih\\," + "720" + "):h=min(" +
                "1280" + "\\,ih*" + "720" + "/iw), pad=w=" + "720" +
                ":h=" + "1280" + ":x=( " + "720" + "-iw)/2:y=(" + "1280" + "-ih)/2,format=yuv420p,setsar=1,setpts=PTS-STARTPTS[v" + i + "];";

        if (isVideoHaveAudioTrack(selectedVideos.get(i).getPath())) {
            str4.append("[").append(i).append(":a]aformat=channel_layouts=stereo:sample_rates=44100,asetpts=PTS-STARTPTS[a").append(i).append("];");
            str5.append("[v").append(i).append("][a").append(i).append("]");
        } else {
            str4.append("[").append(selectedVideos.size()).append(":a]aformat=channel_layouts=stereo:sample_rates=44100,asetpts=PTS-STARTPTS[a").append(selectedVideos.size()).append("];");
            str5.append("[v").append(i).append("][a").append(selectedVideos.size()).append("]");
        }
        str3 = str6;
    }
    commandList.add("-filter_complex");
    commandList.add(str3 + str4 + str5 + "concat=n=" + selectedVideos.size() + ":v=1:a=1[v][a]");
    commandList.add("-map");
    commandList.add("[v]");
    commandList.add("-map");
    commandList.add("[a]");
    commandList.add("-c:v");
    commandList.add("libx264");
    commandList.add("-c:a");
    commandList.add("aac");
    commandList.add("-preset");
    commandList.add("ultrafast");
    commandList.add(filepath);
    return commandList;
}
私有布尔值是VideoHaveAudioTrack(字符串路径){
布尔ISaudioTrack可用;
MediaMetadataRetriever retriever=新的MediaMetadataRetriever();
试一试{
retriever.setDataSource(路径);
String hasAudioStr=retriever.extractMetadata(MediaMetadataRetriever.METADATA\u KEY\u有\u音频);
isAudioTrackAvailable=hasAudioStr!=null&&hasAudioStr.equals(“是”);
}捕获(例外e){
isAudioTrackAvailable=false;
}
返回isAudioTrackAvailable;
}
公共静态链接列表合并视频(ArrayList selectedVideos、字符串静音音频、字符串文件路径){
字符串str3=“”;
StringBuilder str4=新StringBuilder(str3);
StringBuilder str5=新的StringBuilder(str4.toString());
布尔值isAnyMuteVideo=false;
LinkedList commandList=新建LinkedList();
对于(int i=0;i

试试这个,告诉我们这是否适用于ffmpeg日志,以便我们可以通过改进上述答案来帮助您。

显示您的ffmpeg命令和完整日志。我添加了一个日志。