私は注意を払ってきました。この回答ffmpeg
LinuxMintは私のAudibleオーディオブックの一部を変換して再生するために使用されます。各書籍はソースファイルですが、ffmpeg
変換の先頭にすべての章がリストされていることを確認しました。
本を章に分ける方法はありますかffmpeg
?各章を別々のファイルに変換(章別に分割)しますか?単独で使用するのが最善ですが、ffmpeg
他のプログラム/スクリプトを(と一緒にffmpeg
)使用することもオプションです。
(私は(Pythonスクリプトを使用して)DVDを偶数長さのチャンクまたはチャプターに分割することに関する他の答えを見ましたが、ffmpeg
私が探しているものではないので、より簡単な方法があることを願っています。)
ベストアンサー1
私は最近この仕事をやってきました。 Nemoが上記のように、ffprobeはコマンドを使用して章を簡単に開始および終了できるjsonファイルを提供します。
ffprobe -i fileName -print_format json -show_chapters
-sexagesimal
コマンドに追加すると、より読みやすい出力(IMO)が生成され、出力は後で処理するためにファイルにリダイレクトされます。
FFmpegには少し助けが必要だったので、jgとAtomicParsleyも使用しました。前者はJSONファイルを解析し、後者は結果のm4bファイルに画像とメタデータを追加します。
スクリプトはまた、m4aファイルを使用した出力をサポートするか、必要に応じてmp3への変換をサポートします。引数$ 1 - 入力ファイルと(オプション)$ 2出力タイプ(デフォルトはm4b)を使用して呼び出すだけです。
これに基づいて、次のスクリプトを作成しました。
#!/bin/bash
# script to convert m4b (audiobook) files with embedded chapted (for eg. converted from Audbile) into individual chapter files
# required: ffmpeg; jg (json interpreter) & AtomicParsley (to embed pictures and add additional metadata to m4a/m4b AAC files)
# discover the file type (extension) of the input file
ext=${1##*.}
echo "extension: $ext"
# all files / folders are named based on the "shortname" of the input file
shortname=$(basename "$1" ".$ext")
picture=$shortname.jpg
chapterdata=$shortname.dat
metadata=$shortname.tmp
echo "shortname: $shortname"
# if an output type has been given on the command line, set parameters (used in ffmpeg command later)
if [[ $2 = "mp3" ]]; then
outputtype="mp3"
codec="libmp3lame"
elif [[ $2 = "m4a" ]]; then
outputtype="m4a"
codec="copy"
else
outputtype="m4b"
codec="copy"
fi
echo "outputtype: |$outputtype|"
# if it doesn't already exist, create a json file containing the chapter breaks (you can edit this file if you want chapters to be named rather than simply "Chapter 1", etc that Audible use)
[ ! -e "$chapterdata" ] && ffprobe -loglevel error \
-i "$1" -print_format json -show_chapters -loglevel error -sexagesimal \
>"$chapterdata"
read -p "Now edit the file $chapterdata if required. Press ENTER to continue."
# comment out above if you don't want the script to pause!
# read the chapters into arrays for later processing
readarray -t id <<< $(jq -r '.chapters[].id' "$chapterdata")
readarray -t start <<< $(jq -r '.chapters[].start_time' "$chapterdata")
readarray -t end <<< $(jq -r '.chapters[].end_time' "$chapterdata")
readarray -t title <<< $(jq -r '.chapters[].tags.title' "$chapterdata")
# create a ffmpeg metadata file to extract addition metadata lost in splitting files - deleted afterwards
ffmpeg -loglevel error -i "$1" -f ffmetadata "$metadata"
artist_sort=$(sed 's/.*=\(.*\)/\1/' <<<$(cat "$metadata" |grep -m 1 ^sort_artist))
album_sort=$(sed 's/.*=\(.*\)/\1/' <<<$(cat "$metadata" |grep -m 1 ^sort_album))
rm "$metadata"
# create directory for the output
mkdir -p "$shortname"
echo -e "\fID\tStart Time\tEnd Time\tTitle\t\tFilename"
for i in ${!id[@]}; do
let trackno=$i+1
# set the name for output - currently in format <bookname>/<tranck number>
outname="$shortname/$(printf "%02d" $trackno). $shortname - ${title[$i]}.$outputtype"
#outname=$(sed -e 's/[^A-Za-z0-9._- ]/_/g' <<< $outname)
outname=$(sed 's/:/_/g' <<< $outname)
echo -e "${id[$i]}\t${start[$i]}\t${end[$i]}\t${title[$i]}\n\t\t$(basename "$outname")"
ffmpeg -loglevel error -i "$1" -vn -c $codec \
-ss ${start[$i]} -to ${end[$i]} \
-metadata title="${title[$i]}" \
-metadata track=$trackno \
-map_metadata 0 -id3v2_version 3 \
"$outname"
[[ $outputtype == m4* ]] && AtomicParsley "$outname" \
--artwork "$picture" --overWrite \
--sortOrder artist "$artist_sort" \
--sortOrder album "$album_sort" \
> /dev/null
done
必要に応じて、JSONファイル(.datファイル)をAudibleファイルとして編集し、チャプター名を「Chapter 1」、「Chapter 2」などとして指定できます。
例えば。最初は、ファイルの最初の部分を次のように読み取ることができます。
{
"chapters": [
{
"id": 0,
"time_base": "1/1000",
"start": 0,
"start_time": "0:00:00.000000",
"end": 3206908,
"end_time": "0:53:26.908000",
"tags": {
"title": "Chapter 1"
}
},
関連行を単純に変更すると、"title": "Introduction"
結果の分割ファイルが変更されます。