ChurchofJesusChristDev / General-Conference-to-Audiobook

Unofficial guide to convert the official General Conference website listing into an Audiobook for easy listening on any device, in any app.
2 stars 0 forks source link

How to convert to m4b with ffmpeg #1

Open coolaj86 opened 2 years ago

coolaj86 commented 2 years ago

I think it's something like this:

ffmpeg -f concat -safe 0 -i list.txt -vn -y -b:a 64k -acodec aac -ac 2 -f mp4 result.m4b

inputs.txt

file 001-abc.mp3
file 002-xyz.mp3

Not sure if that correctly carries over the chapter info.

References:

coolaj86 commented 11 months ago

m4a-to-ffmetadata.sh:

#!/bin/sh
set -e
set -u

# Output metadata file
output_file="ffmetadata.txt"

# Initialize the metadata file
echo ";FFMETADATA1" > "$output_file"

# Function to escape special characters
fn_escape() { (
    echo "$1" | sed 's/"/\\"/g'
); }

fn_get_duration() { (
    my_file="${1}"

    if command -v mdls > /dev/null; then
        fn_get_duration_mdls "${my_file}"
    else
        # TODO ffprobe
        echo >&2 "non-mac not supported yet"
        return 1
    fi
); }

fn_get_duration_mdls() { (
    my_file="${1}"
    my_secs="$(
        mdls -name kMDItemDurationSeconds -raw "${my_file}"
    )"
    my_ms="$(
        echo "${my_secs} * 1000" |
            bc -l |
            cut -d'.' -f1
    )"

    echo "${my_ms}"
); }

main() { (
    my_start=0
    my_end=0

    echo "Reading metadata from..."
    for my_file in ./m4a/*.m4a; do
        echo "    ${my_file}"

        # show ALL kMD fields
        #mdls "${my_file}"

        my_title="$(
            mdls -name kMDItemTitle -raw "${my_file}"
        )"
        echo >&2 "        Title: ${my_title}"
        my_title="$(
            fn_escape "${my_title}"
        )"

        my_artist="$(
            mdls -name kMDItemAuthors -raw "${my_file}" |
                grep '[a-z]' |
                cut -d"\"" -f2
        )"
        echo >&2 "        Artist: ${my_artist}"
        my_artist="$(
            fn_escape "${my_artist}"
        )"

        my_duration="$(
            fn_get_duration "${my_file}"
        )"
        my_end="$((my_start + my_duration))"

        # Add a chapter entry for the my_file
        {
            echo ''
            echo "[CHAPTER]"
            echo "TIMEBASE=1/1000"
            echo "START=${my_start}"
            echo "END=${my_end}"
            echo "title=\"${my_title}\""
            echo "artist=\"${my_artist}\""
        } >> "${output_file}"

        my_start="$((my_end + 1))"
    done

    echo ''
    echo "Metadata file '${output_file}' created with chapters."
    echo ''
); }

main
coolaj86 commented 11 months ago

Add metadata from original M4As to M4B:

#!/bin/sh
set -e
set -u

my_file="${1}"
my_name="$(
    basename "${my_file}" .m4b
)"
ffmpeg -i "ffmetadata.txt" -i "${my_file}" -map_metadata 1 -codec copy "${my_name}.chapters.m4b"

Still haven't figured out how to add the cover art without yet another tool...