mp4chaps 的 mp3 文件的时间长度
Time length of mp3 files for mp4chaps
我一直在努力使用一些 bash 代码来根据 mp3 文件的时间长度生成一个 mp4chaps.chapters.txt 文件,这样当我将它转换为有声读物 (m4b) 时,我可以重新添加章节信息
我想我已经解决了,但我很好奇这是否可以更优雅地完成?
我的poc代码(假设你运行这个脚本所在的文件夹里有mp3文件):
#!/usr/bin/env bash
echo "00:00:00.000 Chapter 1"
i=2
total_seconds=0
total_millis=0
for mp3 in *.mp3; do
duration=$(ffprobe -v quiet -print_format json -show_format "${mp3}" | jq ".format.duration"|sed 's/"//g')
millisecs="$(echo $duration | awk -F'.' '{print }')"
millisecs="${millisecs#"${millisecs%%[!0]*}"}"
total_millis=$((total_millis + millisecs))
secs=$((total_millis / 1000000))
total_millis=$((total_millis - (secs * 1000000)))
total_seconds=$((total_seconds + $(echo $duration | awk -F'.' '{print }') + secs))
hour=$((total_seconds / (60 * 60)))
minutes=$(((total_seconds - (hour * 60 * 60)) / 60))
seconds=$((total_seconds - (hour * 60 * 60) - (minutes * 60)))
hour=$(printf "%02d" $hour)
minutes=$(printf "%02d" $minutes)
seconds=$(printf "%02d" $seconds)
echo "$hour:$minutes:$seconds.${millisecs:0:3} Chapter $i"
i=$((i + 1))
done
一个mp4chapts.chapters.txt文件的格式是这样的:
00:00:00.000 Chapter 1
00:11:46.612 Chapter 2
00:22:55.525 Chapter 3
00:41:22.670 Chapter 4
01:09:17.337 Chapter 5
ffprobe json格式为:
{
"format": {
"filename": "Book with chapter 01.mp3",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "mp3",
"format_long_name": "MP2/3 (MPEG audio layer 2/3)",
"start_time": "0.025057",
"duration": "706.612245",
"size": "5657329",
"bit_rate": "64050",
"probe_score": 51,
"tags": {
"title": "a good book 01",
"artist": "The Author",
"album": "fantastic album information",
"track": "01",
"publisher": "Good Media, Inc",
"genre": "Fiction",
"comment": "Read by ...",
"copyright": "2019",
"date": "2021"
}
}
}
我使用这个 json 的持续时间。
请您尝试以下操作:
echo "00:00:00.000 Chapter 1"
i=2
total_millis=0
for mp3 in *.mp3; do
duration=$(ffprobe -v quiet -show_entries format=duration "${mp3}" | sed -n 's/duration=//p')
millisecs=$((${duration%.*} * 1000 + 10#${duration#*.} / 1000))
((total_millis += millisecs))
hour=$((total_millis / 3600 / 1000))
mins=$(((total_millis - hour*3600*1000) / 60 / 1000))
secs=$(((total_millis - hour*3600*1000 - mins*60*1000) / 1000))
millis=$((total_millis - hour*3600*1000 - mins*60*1000 - secs*1000))
printf "%02d:%02d:%02d.%03d Chapter %d\n" "$hour" "$mins" "$secs" "$millis" "$i"
((i++))
done
恐怕还是不够优雅。我统一了要累积的变量
进入 total_millis
的时间量使代码更短
比原来的。顺便说一句,你在 echo
中的 millisecs
值
行可能不正确。直接从当前章节计算
不反映 total_millis
.
的值
[备选]
如果你的date
命令支持-d
选项,这里有一个作弊方法:
echo "00:00:00.000 Chapter 1"
i=2
total_secs=0
for mp3 in *.mp3; do
duration=$(ffprobe -v quiet -show_entries format=duration "${mp3}" | sed -n 's/duration=//p')
total_secs=$(echo "$total_secs + $duration" | bc)
day=$(date -d "@$total_secs" -u +%d)
hour=$(( 10#$(date -d "@$total_secs" -u +%H) + (10#$day - 1) * 24 ))
printf "%02d:%s Chapter %d\n" "$hour" "$(date -d "@$total_secs" -u +%M:%S.%3N)" "$((i++))"
done
date
命令的行为在很大程度上取决于平台,上面的解决方案不可移植。
我一直在努力使用一些 bash 代码来根据 mp3 文件的时间长度生成一个 mp4chaps.chapters.txt 文件,这样当我将它转换为有声读物 (m4b) 时,我可以重新添加章节信息
我想我已经解决了,但我很好奇这是否可以更优雅地完成?
我的poc代码(假设你运行这个脚本所在的文件夹里有mp3文件):
#!/usr/bin/env bash
echo "00:00:00.000 Chapter 1"
i=2
total_seconds=0
total_millis=0
for mp3 in *.mp3; do
duration=$(ffprobe -v quiet -print_format json -show_format "${mp3}" | jq ".format.duration"|sed 's/"//g')
millisecs="$(echo $duration | awk -F'.' '{print }')"
millisecs="${millisecs#"${millisecs%%[!0]*}"}"
total_millis=$((total_millis + millisecs))
secs=$((total_millis / 1000000))
total_millis=$((total_millis - (secs * 1000000)))
total_seconds=$((total_seconds + $(echo $duration | awk -F'.' '{print }') + secs))
hour=$((total_seconds / (60 * 60)))
minutes=$(((total_seconds - (hour * 60 * 60)) / 60))
seconds=$((total_seconds - (hour * 60 * 60) - (minutes * 60)))
hour=$(printf "%02d" $hour)
minutes=$(printf "%02d" $minutes)
seconds=$(printf "%02d" $seconds)
echo "$hour:$minutes:$seconds.${millisecs:0:3} Chapter $i"
i=$((i + 1))
done
一个mp4chapts.chapters.txt文件的格式是这样的:
00:00:00.000 Chapter 1
00:11:46.612 Chapter 2
00:22:55.525 Chapter 3
00:41:22.670 Chapter 4
01:09:17.337 Chapter 5
ffprobe json格式为:
{
"format": {
"filename": "Book with chapter 01.mp3",
"nb_streams": 1,
"nb_programs": 0,
"format_name": "mp3",
"format_long_name": "MP2/3 (MPEG audio layer 2/3)",
"start_time": "0.025057",
"duration": "706.612245",
"size": "5657329",
"bit_rate": "64050",
"probe_score": 51,
"tags": {
"title": "a good book 01",
"artist": "The Author",
"album": "fantastic album information",
"track": "01",
"publisher": "Good Media, Inc",
"genre": "Fiction",
"comment": "Read by ...",
"copyright": "2019",
"date": "2021"
}
}
}
我使用这个 json 的持续时间。
请您尝试以下操作:
echo "00:00:00.000 Chapter 1"
i=2
total_millis=0
for mp3 in *.mp3; do
duration=$(ffprobe -v quiet -show_entries format=duration "${mp3}" | sed -n 's/duration=//p')
millisecs=$((${duration%.*} * 1000 + 10#${duration#*.} / 1000))
((total_millis += millisecs))
hour=$((total_millis / 3600 / 1000))
mins=$(((total_millis - hour*3600*1000) / 60 / 1000))
secs=$(((total_millis - hour*3600*1000 - mins*60*1000) / 1000))
millis=$((total_millis - hour*3600*1000 - mins*60*1000 - secs*1000))
printf "%02d:%02d:%02d.%03d Chapter %d\n" "$hour" "$mins" "$secs" "$millis" "$i"
((i++))
done
恐怕还是不够优雅。我统一了要累积的变量
进入 total_millis
的时间量使代码更短
比原来的。顺便说一句,你在 echo
中的 millisecs
值
行可能不正确。直接从当前章节计算
不反映 total_millis
.
[备选]
如果你的date
命令支持-d
选项,这里有一个作弊方法:
echo "00:00:00.000 Chapter 1"
i=2
total_secs=0
for mp3 in *.mp3; do
duration=$(ffprobe -v quiet -show_entries format=duration "${mp3}" | sed -n 's/duration=//p')
total_secs=$(echo "$total_secs + $duration" | bc)
day=$(date -d "@$total_secs" -u +%d)
hour=$(( 10#$(date -d "@$total_secs" -u +%H) + (10#$day - 1) * 24 ))
printf "%02d:%s Chapter %d\n" "$hour" "$(date -d "@$total_secs" -u +%M:%S.%3N)" "$((i++))"
done
date
命令的行为在很大程度上取决于平台,上面的解决方案不可移植。