Skip to content

Instantly share code, notes, and snippets.

@akostadinov
Last active February 18, 2022 11:33
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save akostadinov/9bcdfb42a8cb133f7c50d6748b832f4f to your computer and use it in GitHub Desktop.
ffmpeg split by chapter
#!/usr/bin/env bash
# based on https://stackoverflow.com/a/61525373/520567
# you can play with -metadata and file name as you see fit
set -efu
videoFile="$1"
ffprobe -hide_banner \
"$videoFile" \
-print_format json \
-show_chapters \
-loglevel error |
jq -r '.chapters[] | [ .id, .start_time, .end_time | tostring ] | join(" ")' |
while read chapter start end; do
ffmpeg -nostdin \
-ss "$start" -to "$end" \
-i "$videoFile" \
-map 0 \
-map_chapters -1 \
-c copy \
"${videoFile%.*}-$chapter.${videoFile##*.}";
done
#!/usr/bin/env bash
# based on split_with_cover_playlist.sh
# supported params to override on command line:
# title="whatever" target="whatever" chapter_in_filename=1
set -efu
input="$1"
while shift && [[ "${1:-}" ]]; do
opt="$1"
varname="${opt%%=*}"
varvalue="${opt#*=}"
declare ${varname}="${varvalue}"
done
# for music you can use `--preset extreme`
lame_command='lame --alt-preset standard -a --lowpass 10 -b 32'
EXT2="mp3"
activation_bytes= # "-activation_bytes aax_secret"
json=$(ffprobe $activation_bytes -i "$input" -loglevel error -print_format json -show_format -show_chapters)
[[ "${title:-}" ]] || title=$(echo $json | jq -r ".format.tags.title")
count=$(echo $json | jq ".chapters | length")
if [[ -z "${target:-}" ]]; then
target=$(echo $json | jq -r ".format.tags | .artist + \" - \" + .title")
if [[ "$target" == " -"* ]] || [[ "$target" == *"- " ]]; then
target="${input%.*}"
fi
fi
: ${chapter_in_filename:=}
mkdir "$target"
echo "[playlist]
NumberOfEntries=$count" > "$target/0_Playlist.pls"
for i in $(seq -w 1 $count);
do
j=$((10#$i))
n=$(($j-1))
start=$(echo $json | jq -r ".chapters[$n].start_time")
end=$(echo $json | jq -r ".chapters[$n].end_time")
name=$(echo $json | jq -r ".chapters[$n].tags.title")
if [[ "$chapter_in_filename" ]]; then
filepart=" ${name/\//-}"
else
filepart="-chapter"
fi
ffmpeg $activation_bytes -nostdin -ss $start -to $end -i "$input" -map_chapters -1 -f wav -metadata title="$title $name" pipe:1 | $lame_command - "$target/$i${filepart}.$EXT2"
echo "File$j=$i-chapter.$EXT2" >> "$target/0_Playlist.pls"
done
#!/usr/bin/env bash
# based on https://stackoverflow.com/a/47901982/520567
input="$1"
EXT2="${input##*.}"
# activation_bytes="-activation_bytes aax_secret"
set -e
json=$(ffprobe $activation_bytes -i "$input" -loglevel error -print_format json -show_format -show_chapters)
title=$(echo $json | jq -r ".format.tags.title")
count=$(echo $json | jq ".chapters | length")
target=$(echo $json | jq -r ".format.tags | .date + \" \" + .artist + \" - \" + .title")
mkdir "$target"
ffmpeg $activation_bytes -i "$input" -frames:v 1 -f image2 "$target/cover.jpg"
echo "[playlist]
NumberOfEntries=$count" > "$target/0_Playlist.pls"
for i in $(seq -w 1 $count);
do
j=$((10#$i))
n=$(($j-1))
start=$(echo $json | jq -r ".chapters[$n].start_time")
end=$(echo $json | jq -r ".chapters[$n].end_time")
name=$(echo $json | jq -r ".chapters[$n].tags.title")
ffmpeg $activation_bytes -nostdin -ss $start -to $end -i "$input" -map_chapters -1 -map 0 -c copy -metadata title="$title $name" "$target/$i $name.$EXT2"
echo "File$j=$i $name.$EXT2" >> "$target/0_Playlist.pls"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment