amiaopensource / ffmprovisr

Repository of useful FFmpeg commands for archivists!
https://amiaopensource.github.io/ffmprovisr/
528 stars 66 forks source link

recipe: trim audio silence, lossless #419

Open atomGit opened 4 years ago

atomGit commented 4 years ago

i think quite a few people, myself included, are looking for a clean and lossless method to trim excess silence from only the beginning and end of an audio file, particularly music files, leaving a set amount of silence

while this is possible with ffmpeg and ffprobe, the process involves decoding the audio, reversing it, and decoding again so it's all quite slow

i found this on stack and modified it a bit to make a (sorta) working example, but i see this solution as a very dirty way to accomplish the task, however it is the only thing i was able to hack together after a LOT of searching and reading over the course of several days

#!/bin/bash

#rm -r OUTPUT 2>/dev/null
#rm -r LOSSLESS 2>/dev/null
#rm -r TEMP 2>/dev/null

mkdir TEMP
mkdir OUTPUT
mkdir LOSSLESS

ffmpeg -hide_banner -nostdin -loglevel warning -y -i test.mp3 -vn -af silenceremove=1:0:-70dB TEMP/begincut.mp3
ffmpeg -hide_banner -nostdin -loglevel warning -y -i TEMP/begincut.mp3 -vn -af areverse TEMP/reversed.mp3
ffmpeg -hide_banner -nostdin -loglevel warning -y -i TEMP/reversed.mp3 -vn -af silenceremove=1:0:-70dB TEMP/revcut.mp3
ffmpeg -hide_banner -nostdin -loglevel warning -y -i TEMP/revcut.mp3   -vn -af areverse TEMP/finished.mp3

cp "TEMP/finished.mp3" "OUTPUT/test.mp3"

ORGLENG=$( ffprobe -v warning -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 test.mp3 )
BEGINCT=$( ffprobe -v warning -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 TEMP/begincut.mp3 )
FINLENG=$( ffprobe -v warning -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 TEMP/finished.mp3 )
STARTSILENCE=$( echo "${ORGLENG} ${BEGINCT}" | awk '{printf $1 - $2}' )
ENDSILENCE=$( echo "${BEGINCT} ${FINLENG}" | awk '{printf $1 - $2}' )

echo "ORGLENG=${ORGLENG}"
echo "BEGINCT=${BEGINCT}"
echo "FINLENG=${FINLENG}"
echo "STARTSILENCE=${STARTSILENCE}"
echo "ENDSILENCE=${ENDSILENCE}"

echo "${STARTSILENCE}" | grep -q 'e' && STARTSILENCE="0.0"

# extract framelength in seconds
OFFSET=$( ffprobe test.mp3 -show_frames 2>/dev/null | grep pkt_duration_time | head -n1 | awk -F= '{print $2}' )
# distract frame rate to make sure it is cut in the silence
STARTSILENCE=$( echo "${STARTSILENCE} ${OFFSET}" | awk '{printf $1 - $2}' )
# if it is negative, make it 0
echo "${STARTSILENCE}" | grep -q '-' && STARTSILENCE="0.0"
# add the distracted size to the length
FINLENG=$( echo "${FINLENG} ${OFFSET}" | awk '{printf $1 + $2}' )

echo "test.mp3 = ${ORGLENG} seconds with ${STARTSILENCE}s silence at start and ${ENDSILENCE}s at end. Result is ${FINLENG}s"
echo "Offset = ${OFFSET}"

ffmpeg -hide_banner -nostdin -loglevel warning -y -i test.mp3 -ss ${STARTSILENCE} -t ${FINLENG} -vn -c:a copy LOSSLESS/test.mp3

note that -nostdin seems to be required else funny things seem to happen happen, like chopping off a portion of the audio that contains detectable audio

trivial considering this request, but the script also causes an error when i open the file in Kwave (similar to Audacity):

An error occurred while decoding the file:
'File contains invalid data',
at position 1,044.

related: #367

ablwr commented 4 years ago

Thanks for this issue/recipe! @privatezero I'd be interested to hear your thoughts on this?

richardpl commented 4 years ago

Do you know what lossless even means?

ablwr commented 4 years ago

@richardpl I don't understand what you are implying by asking that. Are you trying to make a disparaging comment? If so, please log off because being rude and condescending is not welcome here.

richardpl commented 4 years ago

I genuinely ask user to give reasoning behind using lossy codecs for lossless trimming.

mercuryswitch commented 4 years ago

I would expect anyone looking here would be fairly well informed of the implications of using a lossy codec. As to giving the reason, that would depend on the person and their use of a lossy codec; usually it's to save on size to transfer over the interwebz or stream etc. lossless trimming to my knowledge is trimming audio to the point of a zero crossing without losing any content, so the lossiness in the context of this recipe is not really the point. That's like saying here is a guide to cut white bread with a slicer, and then saying "do you even know what white bread means.."