#!/bin/bash IFS=$'\n\t' # Author: http://crunchbang.org/forums/viewtopic.php?id=38748#p414992 # m4bronto # https://gist.github.com/dcondrey/469e2850e7f88ac198e8c3ff111bda7c # Modified to support a chapters.txt file with sequential list of chapter names # Run as split-audio-by-chapters file.m4a [chapters.txt] # Output files are sequential and generated # https://stackoverflow.com/a/3352015 trim() { local var="$*" # remove leading whitespace characters var="${var#"${var%%[![:space:]]*}"}" # remove trailing whitespace characters var="${var%"${var##*[![:space:]]}"}" echo -n "$var" } CHAPTER_INDEX=0 if [ -f "$2" ]; then CHAPTERS_FILE_PASSED=1 echo "Reading chapters from $2" readarray CHAPTERS < "$2" IFS=$'\n\r' IFS=$'\n\t' else CHAPTERS_FILE_PASSED=0 fi ffmpeg -i "$1" 2> /tmp/ffmpeg.txt while read -r first _ _ start _ end; do unset IFS if [[ "$first" = "Chapter" ]]; then read -r read -r _ _ CHAPTER_TITLE REAL_CHAPTER_INDEX=$((CHAPTER_INDEX+1)) CHAPTER_INDEX_PADDED=$(printf "%03d" "${REAL_CHAPTER_INDEX}") # If we are using a chapters.txt that is valid if ((CHAPTERS_FILE_PASSED=="1")) ; then CHAPTER_TITLE=${CHAPTERS[$CHAPTER_INDEX]} fi FILENAME="${CHAPTER_INDEX_PADDED} - $(trim "$CHAPTER_TITLE").m4a" # -vsync 2 = Frames are passed through with their timestamp or dropped so as to prevent 2 frames from having the same timestamp. # -sn = no subtitles # -dn = no data stream # -vn = no video stream # -metadata title= put in a chapter title # -acodec copy = copy the audio stream # +faststart = Relocating this moov atom to the beginning of the file can facilitate playback before the file is completely downloaded by the client. ffmpeg -hide_banner -loglevel panic \ -movflags +faststart \ -vsync 2 -sn -dn -vn -i "$1" -ss "${start%?}" -to "$end" -metadata title="$CHAPTER_TITLE" -dn -vn -sn -acodec copy "$FILENAME"