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

标签 ffmpeg

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

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!
这是唯一具有“ float ”分辨率的此类视频,无法与 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;
}
试试这个并告诉我们这是否适用于您的 ffmpeg 日志,以便我们可以通过改进上述答案来帮助您。

关于ffmpeg:处理分辨率变化的视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66482682/

相关文章:

objective-c - Flac 转换器 Objective-C?

ffmpeg - 使用 ffmpeg 合并 mp4 文件(按顺序)

ffmpeg - 使用 ffmpeg 将文件转换为 file.aac

Android FFMPEG 无法识别文件 : protocol

ffmpeg - 创建 FFMPEG 流

android - 如何从android studio链接和调用预构建静态 native 库的功能

android - How to encode jpeg images to H264 very fast(将图像转换为视频)

android - 如何从android中的一组图像制作视频,如flipagram

ffmpeg - 如何将当前目录中 .jpg 和 .png 类型的所有图像转换为 FFmpeg 中的视频?

ffmpeg 将图像连接到一张图像中