Как мне увеличить размер видео до целевого размера?

FWIW, причина, по которой решение @colin-maudry работает, заключается в том, что это известная ошибка, характерная для python_dateutil, как объясняется в этом связанном обсуждении SO:

https://stackoverflow.com/questions/22736014/getting-ioerror-errno-13-permission-denied-when-importing-pandas-datafra

Это известная проблема с 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

2
24.05.2019, 00:47
2 ответа

@philip -ответ Кулинга близок, но отсутствует несколько частей:

  • Требуемый размер в МБ необходимо умножить на 8, чтобы получить скорость передачи данных
  • Для скорости передачи 1 Мбит/с = 1000 кбит/с = 1000000 бит/с; множители не равны 1024 (есть еще один префикс, KiB/s, который равен 1024 B/s, но ffmpeg, похоже, не использует его)
  • Усечение или округление не -целого числа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.

4
14.07.2020, 00:07

Заявление об отказе от ответственности :Похоже, это работает не идеально. Он становится немного большим.

Соединить два других ответа здесь относительно просто:

Предполагая, что вам нужен файл размером 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
1
27.01.2020, 22:08

Теги

Похожие вопросы