I recently ripped my first Blu-Ray audio discs. Here are a few tips I’ve discovered along the way:
tl;dr
Backup the disc using MakeMKV and extract the audio using the updated version of the command under Putting it all together.
Ripping the discs
MakeMKV can be used to rip and, if necessary, decrypt Blu-Ray audio discs. While it is in beta, it can be evaluated by using the current beta key.
I use the complete Blu-Ray backup feature so I have the raw stream files to work with.
ffmpeg can be used to extract the audio track(s) from the video streams on the Blu-Ray.
First interrogate one of your streams using ffprobe
to see how the different tracks are laid out:
ffprobe -hide_banner BDMV/STREAM/00002.m2ts
I use -hide_banner
to reduce the amount of text printed to the terminal. If you have troubles and decide to ask others for help, be sure to omit -hide_banner
as the information it emits can be useful when debugging!
Here is the output I got:
Input #0, mpegts, from 'BDMV/STREAM/00002.m2ts':
Duration: 00:01:47.07, start: 4200.000000, bitrate: 7133 kb/s
Program 1
Stream #0:0[0x1011]: Video: h264 (High) (HDMV / 0x564D4448), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 90k tbn, 47.95 tbc
Stream #0:1[0x1100]: Audio: pcm_bluray (HDMV / 0x564D4448), 48000 Hz, stereo, s16, 1536 kb/s
In my case I only have one audio stream to worry about at address 0:1
. Note it is labelled s16
which means that it is a signed 16-bit depth audio stream. These details will be important in a moment.
Next comes the extraction:
Update 2017-09-10: I now think it is much more straightforward to trust FFMPEG to do the right thing:
for i in BDMV/STREAM/*.m2ts; do ffmpeg -hide_banner -i "$i" -map 0:1 "$(basename "${i%.*}").flac"; done
Note that I do not set the audio codec, and merely set the file extension to .flac
as that is the format that I want.
For reference, this is original command I used:
for i in BDMV/STREAM/*.m2ts; do ffmpeg -hide_banner -i "$i" -map 0:1 -acodec pcm_s16le "$(basename "${i%.*}").wav"; done
The -map 0:1
refers to our address from earlier. The s16
part of -acodec pcm_s16le
matches the description of the stream ffprobe
gave us. We cannot use -acodec copy
as ffmpeg
cannot encode pcm_bluray
.
Make sure to use .wav
at the end of the filename, as ffmpeg
considers it important. I was originally trying to use .pcm
, but all I got was this error message:
[NULL @ 000000000283dc20] Unable to find a suitable output format for '00002.pcm'
If you have multiple streams, re-run this command, changing -map
, -acodec
and the output filename (to not overwrite your previous extractions!) as appropriate.
Removing initial silence
After I had extracted the audio, I noticed that every track had about 1.0-1.6 seconds of silence at the beginning. I had no interest in keeping this, so I used ffmpeg
with the silenceremove
filter:
mkdir no-silence
for i in *.wav; do ffmpeg -i "$i" -af silenceremove=start_periods=1:detection=peak "no-silence/$(basename "$i")"; done
start_periods=1
means remove one block of silence from the beginning of the track, a.k.a. the silence before any audio begins. I use detection=peak
because I know I’m working with audio with digital silence; if you’re working with audio that was originally recorded from analogue, omit this option.
Putting it all together
Incidentally, this filter could have been added to the original extraction command, if I knew that I wanted it at the time. :)
Update 2017-09-10: As above, I now think it is much more straightforward to trust FFMPEG to do the right thing:
for i in BDMV/STREAM/*.m2ts; do ffmpeg -hide_banner -i "$i" -map 0:1 -af silenceremove=start_periods=1:detection=peak "$(basename "${i%.*}").flac"; done
For reference, this is original command I used:
for i in BDMV/STREAM/*.m2ts; do ffmpeg -hide_banner -i "$i" -map 0:1 -acodec pcm_s16le -af silenceremove=start_periods=1:detection=peak "$(basename "${i%.*}").wav"; done
Update 2017-05-14: Changed ${i/.*}
to ${i%.*}
to remove file extensions, as the new way will only remove everything following the last .
in the filename, not the first. Thanks to my good friend Mark Holland-Avery for the suggestion!