#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 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
;
[1][silence1]concat=n=2:v=0:a=1
'
-map
-map
-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!
Вот единственное такое видео с «плавающим» разрешением, которое нельзя объединить с цветным фильтром 320×240.
Комментарии:
1. Покажите свою команду ffmpeg и полный журнал.
2. Я добавил журнал.
Ответ №1:
если я не ошибаюсь, вы просто хотите объединить видео, которые могут иметь разные разрешения, тогда это сработает для вас, взгляните на данный код:
Объяснение: Здесь я создал 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 amp;amp; 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, чтобы мы могли помочь вам, улучшив приведенный выше ответ.