FWIW, причина, по которой решение @colin-maudry работает, заключается в том, что это известная ошибка, характерная для python_dateutil
, как объясняется в этом связанном обсуждении SO:
Это известная проблема с python-dateutil, когда разрешения не установлены правильно в пакете pypi: https://bugs.launchpad.net/dateutil/+bug/1243202. Это не является проблемой для pip, поскольку pip нормализует разрешения, но если вы установите его по-другому, то можете столкнуться с проблемами.
Приведенное решение:
sudo chmod o+r /usr/local/lib/python2.7/dist-packages/python_dateutil-2.2-py2.7.egg/EGG-INFO/top_level.txt
@philip -ответ Кулинга близок, но отсутствует несколько частей:
length
(вместо его точного использования или округления в большую сторону )приведет к тому, что размер файла немного превысит целевой размер -b
указывает среднюю скорость передачи данных. :На практике кодировщик допускает скачок скорости передачи данных, что может привести к превышению целевого размера. Однако вы можете указать максимальную скорость передачи данных, используя -maxrate
и -bufsize
Для моего использования -случай, когда я также хотел жестко запрограммировать битрейт аудио и просто соответствующим образом настроить видео (это тоже кажется более безопасным, я не на 100% уверен, что флаг ffmpeg -b
указывает битрейт для видео и аудио потоков вместе или нет ).
Принимая все это во внимание и ограничивая строго 25 МБ:
target_size=$(( 25 * 1000 * 1000 * 8 )) # 25MB in bits
length=`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4`
length_round_up=$(( ${length%.*} + 1 ))
total_bitrate=$(( $target_size / $length_round_up ))
audio_bitrate=$(( 128 * 1000 )) # 128k bit rate
video_bitrate=$(( $total_bitrate - $audio_bitrate ))
ffmpeg -i input.mp4 -b:v $video_bitrate -maxrate:v $video_bitrate -bufsize:v $(( $target_size / 20 )) -b:a $audio_bitrate output.mp4
Обратите внимание, что когда -maxrate
и -bufsize
ограничивают максимальный битрейт, по необходимости средний битрейт будет ниже, поэтому видео будет меньше целевого размера на целых 5 -10% в моих тестах. (на 20-секундном видео с разными размерами цели ). Значение -bufsize
важно, и расчетное значение, использованное выше (, основанное на целевом размере ), является моим лучшим предположением. Слишком маленький, и он значительно снизит качество и не достигнет целевого размера примерно на 50%, но слишком большой, и я думаю, что он потенциально может превзойти целевой размер?
Чтобы предоставить кодировщику больше гибкости, если у вас нет строгого максимального размера файла, удаление -maxrate
и -bufsize
приведет к улучшению качества, но может привести к превышению целевого размера видео на 5% в моем тесты. Дополнительная информация в документации ,где вы увидите это предупреждение:
Note: Constraining the bitrate might result in low quality output if the video is hard to encode. In most cases (such as storing a file for archival), letting the encoder choose the proper bitrate is the constant quality or CRF-based encoding.
Заявление об отказе от ответственности :Похоже, это работает не идеально. Он становится немного большим.
Соединить два других ответа здесь относительно просто:
Предполагая, что вам нужен файл размером 10 МБ (10485760 байт ), вы можете использовать ffprobe
, чтобы найти продолжительность и заставить оболочку выполнить расчет.
Просто будьте осторожны, потому что ffprobe будет сообщать о десятичных разрядах, которые сбивают с толку арифметику оболочки. Я использовал ${length%.*}
, чтобы убрать десятичные разряды :
size=10485760
length=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4)
ffmpeg -i input.mp4 -b $(( $size / ${length%.*} )) output.mp4