Ffmpeg/avconv: транскод с использованием того же кодека и параметров как входной

Есть ли способ сказать ffmpeg и/или avconv использовать для вывода тот же кодек, что и тот, с которым кодируется вход, но выполните перекодировку?

Я ищу что-то вроде:

ffmpeg -i input.mp4 -vcodec same_as_input output.mp4

Обратите внимание, что я не ищу -vcodec copy, так как это копирует поток без перекодирования. Я хочу, чтобы он выполнял транскодирование, но использовал тот же кодек, с которым кодируется входной файл.

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

Приведенный выше пример может показаться глупым, потому что он упрощен (результат будет таким же, как и копирование), но представьте, что я добавляю некоторую обработку, например. время начала и длину, или даже что-то более сложное, например, добавление оверлейного изображения, но я хочу убедиться, что он закодирован с одним и тем же кодировщиком (и, возможно, с теми же параметрами), что и входной файл.

Ответ 1

ffmpeg не имеет функции для копирования той же скорости передачи битов, но он автоматически копирует частоту кадров, ширину, высоту, формат пикселей, формат изображения, количество аудиоканалов, частоту дискретизации звука и т.д. (зависит от кодера).

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

Однако вот простой скрипт bash. Вам нужно будет адаптировать его для включения информации о аудиопотоке и любых других параметров, которые вы хотите.

#!/bin/bash
# Copies the same video codec and bitrate: usually this is not a good idea.
# Usage: ./vidsame input output

echo "Calculating video bitrate. This can take a while for long videos."

# Alternatively you could just use ffprobe to get video stream bitrate,
# but not all inputs will show stream bitrate info, so ffmpeg is used instead.

size="$(ffmpeg -i "$1" -f null -c copy -map 0:v:0 - |& awk -F'[:|kB]' '/video:/ {print $2}')"
codec="$(ffprobe -loglevel error -select_streams v:0 -show_entries stream=codec_name -of default=nk=1:nw=1 "$1")"
duration="$(ffprobe -loglevel error -select_streams v:0 -show_entries format=duration -of default=nk=1:nw=1 "$1")"
bitrate="$(bc -l <<< "$size"/"$duration"*8.192)"

ffmpeg -i "$1" -c:v "$codec" -b:v "$bitrate"k "$2"

echo
echo "Duration: $duration seconds"
echo "Video stream size: $size KiB"
echo "Video bitrate: $bitrate kb/s"
echo "Video codec: $codec"

Если вам нужны дополнительные параметры, используйте ffprobe для просмотра списка доступных:

ffprobe -loglevel error -show_streams input.mkv

Затем используйте -select_entries как показано в сценарии.

Обратите внимание, что codec_name не всегда совпадает с именем кодировщика, но обычно это просто работа. Смотрите ffmpeg -encoders.

Ответ 2

Это похоже на работу

file="input.mp4"
ffmpeg -re -y -i "$file"  -c:v `ffprobe $file |& grep 'Video:' | awk -v N=4 '{print $N}'`  -b:v `ffprobe $file |& grep 'Video:' | awk -v N=15 '{print $N}'`k -f flv output.mp4

Ключ здесь - это эта часть, которая захватывает видеокодек из входного файла. Вы заметите, что это появляется дважды в заявлении, во второй раз он захватывает битрейт.

`ffprobe $file |& grep 'Video:' | awk -v N=4 '{print $N}'`