Как добавить / удалить видео / аудио клип с неизвестной продолжительностью?

19

Я работаю над проектом, в котором я использую ffmpeg для пакетной конвертации некоторых видеофайлов и добавляю эффекты постепенного появления / исчезновения в начале и в конце каждого клипа.

Я использовал этот фрагмент кода, чтобы добавить эффект исчезновения / клипа на клипы с известной длительностью:

ffmpeg -i clip.mp4 -filter:v 'fade=in:0:30,fade=out:9650:30' -c:v libx264 -crf 22 -preset veryfast -c:a copy fadeInOut.mp4

Мои два вопроса:

  1. Как я могу одновременно затухать аудио вход / выход?
  2. Может ли ffmpeg автоматически определить длительность клипа и просто сказать, что последние 30 кадров исчезают?

Благодарность!

d13
источник

Ответы:

15

# 1 Для одновременного затухания аудио входа / выхода:

ffmpeg -i clip.mp4 -vf 'fade=in:0:30,fade=out:960:30'
                   -af 'afade=in:st=0:d=1,afade=out:st=32:d=1'
       -c:v libx264 -crf 22 -preset veryfast fadeInOut.mp4

Время затухания в секундах .

# 2 автоматически? Нет. Но смотрите обходной путь ниже

Вы можете сначала запустить ffprobe, чтобы получить длительность.

ffprobe -i clip.mp4 -show_entries stream=codec_type,duration -of compact=p=0:nk=1

Вы получите что-то вроде этого:

video|13.556000
audio|13.816000

Затем вы можете использовать вышеупомянутое, чтобы разместить ваши угасания. Эти времена в секундах.

Временное решение

ffmpeg -i clip.mp4 -sseof -1 -copyts -i clip.mp4 -filter_complex
       "[1]fade=out:0:30[t];[0][t]overlay,fade=in:0:30[v];
        anullsrc,atrim=0:2[at];[0][at]acrossfade=d=1,afade=d=1[a]"
       -map "[v]" -map "[a]" -c:v libx264 -crf 22 -preset veryfast -shortest fadeInOut.mp4

FFmpeg имеет sseofопцию, которая позволяет искать вход с конца. Мы можем использовать это для достижения нашей цели. Таким образом, мы вводим данные дважды, причем во второй раз принимаем только последнюю секунду. Мы говорим FFmpeg сохранять временные метки, чтобы ffmpeg сохранял временную позицию этой хвостовой части.

Мы применяем замирание к этому хвосту , а затем наложить результат на полный ввод. Поскольку они представляют собой один и тот же мультимедийный файл, передний план полностью покрывает фон, и поскольку он copytsбыл применен, наложение происходит на соответствующий идентичный кадр на входе фона.

Для аудио мы создаем пустой фиктивный звук длительностью 2 секунды, а затем применяем к этому фиктивному аудио кроссфейд из основного аудио. Так как 2-й звук пустой, это, по сути, затухание для основного входа. -shortestДобавляют , чтобы оставить из частей фиктивного аудио после того , как произошла склейка.

Gyan
источник
Это дает ошибку "нет такого фильтра!" для аудио фильтра.
felwithe
1
Есть 4 аудио фильтров , используемые. Который из? Запустите вашу команду с -reportдобавленным и поделитесь отчетом.
Гьян
7

Это ужасный хак, но это может сработать, если все, что вы хотите сделать, это добавить / вывести звук, но не знаете точно, как долго будет длиться клип:

ffmpeg -i input.mp4 -filter_complex "afade=d=0.5, areverse, afade=d=0.5, areverse" output.mp4

[edit 2019-07-24: обратите внимание, что это решение не подходит для потоковых решений, поскольку требует обработки полной дорожки до того, как первый байт может быть передан в поток]

Другой вариант, который я должен использовать acrossfadeс тихой дорожкой:

ffmpeg -i input.mp4 -filter_complex "aevalsrc=0:d=0.6 [a_silence]; [0:a:0] [a_silence] acrossfade=d=0.6" output.mp4
marekventur
источник
3
Это на самом деле довольно элегантно :-)
bk138
это прекрасно работает не могли бы вы объяснить, как это работает. пытаясь разобраться в документации ..
Оберхамси
1
@oberhamsi: Вариант 1: первый фильтр добавляет затухание в начале дорожки. Затем обратный звук и добавляет еще замирание в начале (который на самом деле конец). Наконец трек снова перевернут. Вариант 2 создает беззвучный трек за 0,6 секунды и накладывает на него то же время, что и исходный трек. Все фильтры и их использование описаны здесь: ffmpeg.org/ffmpeg-filters.html (хотя я должен согласиться, что это немного загадочно)
marekventur
3

Ответ на вопрос 2 - ДА! Я искал ту же функциональность, и в итоге я написал сценарий bash, который запрашивает продолжительность затухания в секундах и вычисляет начальный кадр для затухания:

#!/bin/bash

f="$*" # all args
p="${f##*/}" # file
fn="${p%.*}" # name only
e="${p##*.}" # extension

echo
echo $f
echo $p
echo $fn
echo $e
echo

read -e -p "Number of seconds of fade-out: " -i 1 sec # prompt for fade duration in seconds

r=$(ffprobe -show_streams "$f" 2> /dev/null | grep r_frame_rate | head -1 | cut -d \= -f 2) # frame rate
let "frames = $r * $sec" # duration of fade as number of frames
echo $r
echo $sec
echo $frames
lf=$(ffprobe -show_streams "$f" 2> /dev/null | grep nb_frames | head -1 | cut -d \= -f 2) # total number of frames
let "lf = $lf - $frames" # initial frame to start fade at

ffmpeg -loglevel quiet -i "$f" -vf fade=out:$lf:$frames -r $r -vcodec libx264 -preset slow -crf 12 -bf 2 -flags +cgop -pix_fmt yuv420p -acodec copy "$fn $sec sec fade-out.$e"
open "$fn $sec sec fade-out.$e"

Затухания требуют повторного кодирования, поэтому использование низкого crfзначения для libx264обеспечивает высокое качество повторного кодирования. Комментарии должны объяснить все остальное.

hmj6jmh
источник
Ответ на вопрос 2 является ДА! -> это все еще нет. Вопрос: Может ли ffmpeg автоматически определить продолжительность ... но вы написали скрипт, который запускает несколько команд ff * для этого. Полезно для * nix систем.
Гаян
Понятно, вы настаиваете, что ВАШ ответ все еще верен? Если вы будете следовать моему сценарию, вы увидите, что он действительно automatically figure out the durationиспользует ffprobe, который устанавливается с помощью ffmpeg. Кто нибудь говорил о каких-либо ограничениях на количество команд или *nix? Похоже, что ОП использует версию UNIX. Нет .exeв ffmpegкоманде. Я сам использую то, на OS Xчем построен, UNIXно нет UNIX.
hmj6jmh
1
* Если вы будете следовать моему сценарию, вы увидите, что он действительно автоматически выясняет * -> ваш сценарий делает, ffmpeg - нет.
Gyan
Но ffprobeявляется неотъемлемой частью ffmpegраспределения. Вы выбираете гниды, чтобы сохранить лицо IMO.
hmj6jmh
Я должен согласиться, что что-то, что делается скриптом bash, не является чем-то, что автоматически делает ffmpeg. Но если это работает, это способ обойти эту проблему. Отсюда и термин «обходной путь». Я не могу сказать, работает ли это, потому что у меня, как и у большинства людей, нет системы bash или unix. +1 за усилие в любом случае.
ashleedawg