Как получить реальную, фактическую продолжительность файла MP3 (VBR или CBR) на стороне сервера
Я использовал для вычисления продолжительности файлов MP3 файлов на стороне сервера, используя ffmpeg, который, казалось, работал нормально. Сегодня я обнаружил, что некоторые вычисления были неправильными. Почему-то, по какой-то причине, ffmpeg будет просчитывать продолжительность и, кажется, происходит только с файлами с переменной скоростью передачи в битрейтах.
При локальном тестировании я заметил, что ffmpeg напечатал две дополнительные строки зеленым цветом.
Используемая команда:
ffmpeg -i song_9747c077aef8.mp3
ffmpeg говорит:
[mp3 @ 0x102052600] max_analyze_duration 5000000 reached at 5015510
[mp3 @ 0x102052600] Estimating duration from bitrate, this may be inaccurate
После приятного теплого сеанса google я обнаружил некоторые сообщения об этом, но решение не найдено.
Затем я попытался увеличить максимальную продолжительность:
ffmpeg -analyzeduration 999999999 -i song_9747c077aef8.mp3
После этого ffmpeg вернул только вторую строку:
[mp3 @ 0x102052600] Estimating duration from bitrate, this may be inaccurate
Но в любом случае рассчитанная продолжительность была просто неправильной. Сравнивая его с VLC, я заметил, что продолжительность правильная.
После нескольких исследований я наткнулся на mp3info - который я установил и использовал.
mp3info -p "%S" song_9747c077aef8.mp3
mp3info затем вернула длительность CORRECT, но только как целое число, которое я не могу использовать, поскольку мне нужно более точное число здесь. Причина этого была объяснена в комментарии ниже, пользователем blahdiblah - mp3info просто вытаскивает ID3-информацию из файла и фактически не выполняет никаких вычислений.
Я также попытался использовать mplayer для извлечения продолжительности, но так же, как ffmpeg, mplayer возвращает неправильное значение.
Ответы
Ответ 1
Наконец-то я нашел правильное решение этой проблемы с помощью sox, которое возвращает правильную информацию.
sox file.mp3 -n stat
Samples read: 19321344
Length (seconds): 219.062857
Scaled by: 2147483647.0
Maximum amplitude: 1.000000
Minimum amplitude: -1.000000
Midline amplitude: -0.000000
Mean norm: 0.141787
Mean amplitude: 0.000060
RMS amplitude: 0.191376
Maximum delta: 0.947598
Minimum delta: 0.000000
Mean delta: 0.086211
RMS delta: 0.115971
Rough frequency: 4253
Volume adjustment: 1.000
Длина (в секундах): 219.062857
Ответ 2
Вы можете полностью декодировать файл, чтобы получить фактическую продолжительность:
ffmpeg -i input.mp3 -f null -
Вторая в последней строке вывода консоли будет выглядеть примерно так:
size=N/A time=00:03:49.12 bitrate=N/A
Где time
- фактическая продолжительность. В этом примере весь процесс занял около 0,5 секунды.
Ответ 3
Расширение решения от LordNeckbeard. Чтобы получить только статистику, вы можете добавить флаги -v тихий -stats
ffmpeg -v quiet -stats -i input.mp3 -f null -
Ответ 4
Проще использовать ffmpeg для копирования файла из файла с ошибочной продолжительностью в его тег ID3. Это заставляет его писать правильную информацию.
ffmpeg -i "audio.mp3" -acodec copy "audio_fixed.mp3"
Поскольку он использует копирование, он занимает часть времени, которое занимает оригинальная кодировка. Это едва заметно в песне, но вы действительно оцените ее с 7-часовой аудиокнигой. После перекодирования тег ID3" Duration" теперь содержит правильную информацию.
Ответ 5
AV_LOG_FORCE_NOCOLOR=y ffmpeg -nostdin -hide_banner -nostats -loglevel info -i audio.mp3 -f null -vn -c:a copy - 2>&1 | tail -n 2
if [[ "$(AV_LOG_FORCE_NOCOLOR=y ffmpeg -nostdin -hide_banner -nostats -loglevel info -i video.mp4 -f null -c copy - 2>&1 | tail -n 2 | head -n 1)" =~ \ time=([0-9]+):([0-9]{2}):([0-9]{2})\.([0-9]+) ]]; then
declare duration=0 us="${BASH_REMATCH[4]}" t
for t in "${BASH_REMATCH[@]:1:3}"; do
((duration *= 60))
((duration += ${t#0} ))
done
while [ ${#us} -lt 6 ]; do us+=0; done
((us >= 500000)) && ((duration++))
((duration)) || ((duration++))
fi
echo -E Duration: "$duration"