Сжатие медиа для экономии места
Дисклеймер
Методы используемые в этой статье сжимают медиа файлы с большой потерей качества. Прежде чем удалить исходные файлы убедитесь, что сжатые вас удовлетворяют.
В статье могут присутствовать неточности.
Статья не покрывает все параметры и тонкости использования
ffmpeg
, за дополнительной информацией обращайтесь к документации или другим ресурсам.
TL; DR
Для сжатия аудио-файлов лучшим вариантом является использование кодека libopus
в режиме vbr on
с битовой частотой 48k
. Это позволило сжать 22 ГБ аудио до 5 ГБ с приемлемым качеством звука.
ffmpeg -i input.mp3 -c:a libopus -b:a 48k -frame_duration 60 -vbr on output.opus
Введение
В данной статье представлены способы сжатия медиа файлов с целью уменьшения их размера. И используемые методы не являются методами сжатия без потерь, и они находятся на грани «ну в целом не мыло и глаз не режет» или «вроде бас нормальный и не шипит», но потерю качества можно легко заметить или услышать.
Моя мотивация. Со временем у меня собралось огромное количество мемов, видео записей событий и музыки. Которые в сумме занимают более 50 ГБ и мне нужно это хранить и передавать. У меня нет возможности увеличить свое электронное пространство и часто кидаю мемы, которые иногда весят более 10 МБ. И уменьшив размер медиа файлов у меня появится больше свободного места и передаваться эти файлы станут быстрее.
Сведения об ffmpeg
FFmpeg — инструмент для обработки мультимедийных данных, который позволяет кодировать, декодировать, транскодировать, мультиплексировать, демультиплексировать, потоково передавать, фильтровать и проигрывать практически любые аудио- и видео-форматы.
Установка. Если у вас Windows, следуйте инструкциям на страницах Download FFmpeg или Как установить программу FFmpeg в Windows. Иначе загружайте из пакетного менеджера.
Синопсис:
ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...
Общие параметры:
-i url
— Указывает URL входного файла.-y
— Перезаписывает выходные файлы без запроса.-n
— Не перезаписывает выходные файлы и немедленно завершает работу, если указанный выходной файл уже существует.-c[:stream_specifier] codec
или-codec[:stream_specifier] codec
— Выбирает кодек (кодировщик при использовании перед выходным файлом или декодер при использовании перед входным файлом) для одного или нескольких потоков.codec
— это имя декодера/кодировщика или специальное значениеcopy
(только для выхода), указывающее, что поток не должен быть перекодирован. Для каждого потока применяется последняя соответствующая опция-c
.-filter[:stream_specifier] filtergraph
— Создает фильтр-граф, указанный вfiltergraph
, и использует его для фильтрации потока.
Примеры использования:
ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mkv # Конвертация MP4 в MKV с использованием кодеков libx264 и aac
ffmpeg -i input.mp4 -q:a 0 -map a output.mp3 # Извлечение аудиодорожки в формате MP3 с высоким качеством
ffmpeg -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4 # Обрезка видео с 1 минуты до 2 минут без перекодирования
ffmpeg -i input.mp4 -vf "scale=1280:720" output.mp4 # Изменение разрешения видео до 1280x720
ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" output.mp4 # Наложение водяного знака на видео в позиции (10,10)
Сжатие аудио
Есть два формата в которые можно перекодировать MP3 для его сжатия, а именно: AAC и OPUS.
Общие параметры аудио кодеков
-b
— Устанавливает битовую частоту в битах/с.-acodec codec
— Устанавливает аудио-кодек. Это псевдоним для-codec:a
.-aq q
— Устанавливает качество аудио (специфично для кодека, VBR). Это псевдоним для-q:a
.
Из MP3 в AAC
Кодировщики:
Fraunhofer FDK AAC
libfdk_aac
audiotoolbox Encoder
aac_at
(обычно доступен только на MacOS)Native FFmpeg AAC Encoder
aac
(По умолчанию)
Профили:
aac_low
(1): Low Complexity AAC (LC) (По умолчанию) — Высокая совместимость, низкое потребление процессорной мощности. Аудио приемлемо звучит с битовой частотой 128k.aac_he
(4): High Efficiency AAC (HE-AAC) — Низкая совместимость, высокое потребление процессорной мощности, хорошо звучит на низких битовых частотах. Аудио приемлемо звучит с битовой частотой 64k.aac_he_v2
(28): High Efficiency AAC version 2 (HE-AACv2) — Улучшенная версия HE-AAC, лучшее качество звука на низких битовых частотах. Аудио приемлемо звучит с битовой частотой 32k.
Какой кодек выбрать? Если доступен выбирайте aac_at
, иначе libfdk_aac
.
Для AAC-LC:
aac_at
≥libfdk_aac
> (aac
).Для HE-AAC неясно, что лучше:
aac_at
илиlibfdk_aac
.
Какой профиль выбрать? Выбирайте HE-AACv2.
Я выбрал aac_at
c профилем HE-AACv2, если вы собираетесь использовать libfdk_aac
я думаю у вас не будет большого отличия.
Параметры
-q:a
— Устанавливает качество для режима переменной битовой частоты (VBR).-profile:a
— Устанавливает аудио профиль.-b:a
— Устанавливает битовую частоту в битах/с. Если битовая частота не указана явно, она автоматически устанавливается на подходящее значение в зависимости от выбранного профиля. Если включен режим VBR, эта опция игнорируется.
Параметры aac_at
Параметры libfdk_aac
-vbr
— Устанавливает режим VBR, от 1 (низшее качество) до 5 (высокое качество). Значение 0 отключает VBR, и включается CBR (постоянная битовая частота). В настоящее время только профильaac_low
поддерживает кодирование VBR.0
: отключить VBR (По умолчанию)1
: 32 кбит/с на канал2
: 40 кбит/с на канал3
: 48–56 кбит/с на канал4
: 64 кбит/с на канал5
: около 80–96 кбит/с на канал
Из MP3 в OPUS
При малых битовых частотах OPUS звучит хорошо только в стерео, в моно звучит хуже чем AAC.
Кодировщик доступен только один libopus
. Он не поддерживает кодирование, основанное на качестве.
Параметры
-b:a
— Устанавливает битовую частоту в битах/с.-vbr
— Устанавливает режим VBR. Опция-vbr
в FFmpeg имеет следующие допустимые аргументы, с эквивалентными опциями в opusenc в скобках:off (hard-cbr)
: Использует кодирование с постоянной битовой частотой.on (vbr)
: Использует кодирование с переменной битовой частотой (по умолчанию).constrained (cvbr)
: Использует кодирование с ограниченной переменной битовой частотой.
-frame_duration
— Устанавливает максимальный размер кадра или длительность кадра в миллисекундах. Аргумент должен быть одним из следующих значений: 2.5, 5, 10, 20, 40, 60. Меньшие размеры кадров обеспечивают меньшую задержку, но меньшее качество при заданной битовой частоте. Размеры больше 20 мс интересны только при достаточно низких битовых частотах. Значение по умолчанию — 20 мс.
Пример команд
ffmpeg -i input.mp3 -c:a aac output.m4a # Явное указание кодека aac (aac), который используется по умолчанию
ffmpeg -i input.mp3 -c:a libopus output.m4a # Использование кодека libopus (opus)
ffmpeg -i input.mp3 -c:a libfdk_aac output.m4a # Использование кодека libfdk_aac (aac)
ffmpeg -i input.mp3 -c:a libfdk_aac -profile:a aac_he -b:a 64k output.m4a # Использование профиля AAC HE первой версии
ffmpeg -i input.mp3 -c:a libfdk_aac -profile:a aac_he_v2 -b:a 32k output.m4a # Использование профиля AAC HE второй версии
ffmpeg -i input.mp3 -c:a aac_at -profile:a 4 -b:a 64k output.m4a # Использование профиля AAC HE первой версии для кодека aac_at (aac)
ffmpeg -i input.mp3 -c:a aac_at -profile:a 28 -b:a 32k output.m4a # Использование профиля AAC HE второй версии для кодека aac_at (aac)
ffmpeg -i input.mp3 -q:a 10 output.m4a # Указание качества 10 (0-14, 0 - самое высокое качество)
ffmpeg -i input.mp3 -b:a 128k output.m4a # Указание битовой частоты
Таблица сравнения кодеков
Оригинальный файл | Кодек | Битовая частота (Качество) | Режим кодирования | Размер файла (МБ) | Относительный размер (%) | Качество на мой слух |
---|---|---|---|---|---|---|
11 — Drop Dead.mp3 | mp3 | 192k | 4.333 | |||
aac | 192k | cbr | 1.100 | 25 | Идентично | |
aac | 192k | abr | 1.114 | 25 | Идентично | |
opus | 192k | cbr | 4.356 | 100 | Идентично | |
opus | 192k | cvbr | 4.342 | 100 | Идентично | |
opus | 192k | vbr | 4.115 | 94 | Идентично | |
aac | 16k | cbr | 0.468 | 10 | Ужасно | |
aac | 16k | abr | 0.474 | 10 | Ужасно | |
aac | 16k | cvbr | 0.497 | 11 | Плохо | |
opus | 16k | cbr | 0.369 | 8 | Плохо | |
opus | 16k | cvbr | 0.365 | 8 | Плохо | |
opus | 16k | vbr | 0.324 | 7 | Плохо | |
aac | 32k | cbr | 0.739 | 17 | Средне | |
aac | 32k | abr | 0.746 | 17 | Лучше среднего | |
aac | 32k | cvbr | 0.812 | 18 | Похоже на оригинал | |
opus | 32k | cbr | 0.730 | 16 | Лучше среднего | |
opus | 32k | cvbr | 0.725 | 16 | Похоже на оригинал | |
opus | 32k | vbr | 0.663 | 15 | Похоже на оригинал | |
aac | 48k | cbr | 1.100 | 25 | Похоже на оригинал | |
aac | 48k | abr | 1.114 | 25 | Похоже на оригинал | |
aac | 48k | cvbr | 1.194 | 27 | Похоже на оригинал | |
opus | 48k | cbr | 1.094 | 25 | Похоже на оригинал | |
opus | 48k | cvbr | 1.089 | 25 | Похоже на оригинал | |
opus | 48k | vbr | 1.006 | 23 | Похоже на оригинал | |
aac | 0 (117.551k) | vbr | 2.671 | 61 | Похоже на оригинал | |
aac | 7 (52.184k) | vbr | 1.195 | 27 | Похоже на оригинал | |
aac | 14 (19.059k) | vbr | 0.447 | 10 | Хуже среднего | |
3 — This Is Halloween.mp3 | mp3 | 192k | 4.647 | |||
aac | 192k | cbr | 1.180 | 25 | Идентично | |
aac | 192k | abr | 1.191 | 25 | Идентично | |
opus | 192k | cbr | 4.672 | 100 | Идентично | |
opus | 192k | cvbr | 4.669 | 100 | Идентично | |
opus | 192k | vbr | 4.396 | 94 | Идентично | |
aac | 16k | cbr | 0.502 | 10 | Ужасно | |
aac | 16k | abr | 0.505 | 10 | Ужасно | |
aac | 16k | cvbr | 0.538 | 11 | Хуже среднего | |
opus | 16k | cbr | 0.396 | 8 | Плохо | |
opus | 16k | cvbr | 0.392 | 8 | Плохо | |
opus | 16k | vbr | 0.336 | 7 | Плохо | |
aac | 32k | cbr | 0.793 | 17 | Средне | |
aac | 32k | abr | 0.795 | 17 | Лучше среднего | |
aac | 32k | cvbr | 0.866 | 18 | Похоже на оригинал | |
opus | 32k | cbr | 0.783 | 16 | Лучше среднего | |
opus | 32k | cvbr | 0.779 | 16 | Похоже на оригинал | |
opus | 32k | vbr | 0.702 | 15 | Похоже на оригинал | |
aac | 48k | cbr | 1.180 | 25 | Похоже на оригинал | |
aac | 48k | abr | 1.191 | 25 | Похоже на оригинал | |
aac | 48k | cvbr | 1.256 | 27 | Похоже на оригинал | |
opus | 48k | cbr | 1.174 | 25 | Похоже на оригинал | |
opus | 48k | cvbr | 1.170 | 25 | Похоже на оригинал | |
opus | 48k | vbr | 1.066 | 22 | Похоже на оригинал | |
aac | 0 (116.671k) | vbr | 2.844 | 61 | Похоже на оригинал | |
aac | 7 (50.616k) | vbr | 1.244 | 26 | Похоже на оригинал | |
aac | 14 (19.209k) | vbr | 0.483 | 10 | Хуже среднего |
Заключение
Я решил использовать кодек libopus
в режиме vbr on
с битовой частотой 48k
. И в итоге смог сжать 22 ГБ аудио в 5 ГБ.
Вот какой скрипт я использовал для этой задачи:
#!/opt/homebrew/bin/fish
function user_confirmation -d "Get confirmation from user" -a message
set -q message[1]
or set -f message "Do you want to continue?"
while true
read -l -P "$message [y/N] " answer
switch $answer
case Y y
return 0
case '' N n
return 1
end
end
end
set COMPRESSED ./Compressed
set YANDEX_MUSIC ./YandexMusic
set YOUTUBE_MUSIC ./YoutubeMusic
if not test -d $YANDEX_MUSIC
and not test -d $YOUTUBE_MUSIC
echo One or all source directories not exist.
exit 1
end
if not test -d $COMPRESSED
mkdir $COMPRESSED
end
if user_confirmation "Do you want to reset COMPRESSED directory"
rm -r $COMPRESSED/*
read -l -P "Copy (c) or Move (m) from source directories? [C/m] " answer
switch $answer
case M m
mv $YANDEX_MUSIC/* $COMPRESSED/
mv $YOUTUBE_MUSIC/* $COMPRESSED/
case '' C c
cp -a $YANDEX_MUSIC/. $COMPRESSED
cp -a $YOUTUBE_MUSIC/. $COMPRESSED
case '*'
exit 1
end
or exit 1
end
set files (find $COMPRESSED -type f -name '*.mp3')
for file in $files
set new_file (path change-extension '' $file)
ffmpeg -i "$file" -c:a libopus -b:a 48k -frame_duration 60 -vbr on "$new_file".opus
and rm "$file"
end
Переписанный нейросетью скрипт для bash (не запускал):
#!/bin/bash
user_confirmation() {
local message="${1:-Do you want to continue?}"
while true; do
read -p "$message [y/N] " answer
case $answer in
[Yy]* ) return 0;;
[Nn]* | "" ) return 1;;
* ) echo "Please answer yes or no.";;
esac
done
}
COMPRESSED="./Compressed"
YANDEX_MUSIC="./YandexMusic"
YOUTUBE_MUSIC="./YoutubeMusic"
if [ ! -d "$YANDEX_MUSIC" ] && [ ! -d "$YOUTUBE_MUSIC" ]; then
echo "One or all source directories do not exist."
exit 1
fi
if [ ! -d "$COMPRESSED" ]; then
mkdir "$COMPRESSED"
fi
if user_confirmation "Do you want to reset COMPRESSED directory"; then
rm -r "$COMPRESSED"/*
read -p "Copy (c) or Move (m) from source directories? [C/m] " answer
case $answer in
[Mm]* )
mv "$YANDEX_MUSIC"/* "$COMPRESSED"/
mv "$YOUTUBE_MUSIC"/* "$COMPRESSED"/
;;
[Cc]* | "" )
cp -a "$YANDEX_MUSIC"/. "$COMPRESSED"
cp -a "$YOUTUBE_MUSIC"/. "$COMPRESSED"
;;
* )
exit 1
;;
esac
else
exit 1
fi
files=$(find "$COMPRESSED" -type f -name '*.mp3')
for file in $files; do
new_file="${file%.mp3}"
ffmpeg -i "$file" -c:a libopus -b:a 48k -frame_duration 60 -vbr on "${new_file}.opus"
if [ $? -eq 0 ]; then
rm "$file"
fi
done