ytdlcue.sh
· 3.5 KiB · Bash
原始檔案
#!/bin/bash
# CUE-sheet generator for youtube-dl
# Usage:
# 0. Install 'jq' utility
# 1. Download any audio file with metadata from YouTube or Youtube Music, e.g.
# $ youtube-dl \
# --extract-audio \
# --audio-format flac \
# --audio-quality 0 \
# --format bestaudio \
# --write-info-json \
# --output "/tmp/ytm/%(playlist_title)s/%(channel)s - %(title)s.%(ext)s" \
# https://www.youtube.com/watch?v=lVpDQnXz34M
#
# If audio file is already downloaded earlier then just fetch only its metadata:
# $ youtube-dl \
# --write-info-json \
# --skip-download \
# --output "/tmp/ytm/%(playlist_title)s/%(channel)s - %(title)s.%(ext)s" \
# https://www.youtube.com/watch?v=lVpDQnXz34M
#
# 2. Audio and metadata files MUST be named exactly similar (except extenstion),
# but it is not necessary to keep original names. Also they MUST be placed in
# the same directory. Example:
# /tmp/ytm/ABGT496.flac
# /tmp/ytm/ABGT496.info.json
#
# 3. To create CUE file run ytdlcue with a path to audio file:
# $ ytdlcue.sh /tmp/ytm/ABGT496.flac
#
# A new file will be created in the same directory:
# /tmp/ytm/ABGT496.cue
installed() {
command -v "$1" >/dev/null 2>&1
}
! installed 'jq' && {
echo "ERROR: you need to install jq!"
exit 1
}
audio_path="$1" # path to audiofile
audio_file=`basename "$audio_path"` # audiofile name with extension
audio_name=${audio_file%.*} # audiofile name without extension
audio_ext=${audio_file##*.} # audiofile name extension
path="`dirname "$audio_path"`/$audio_name" # path to audiofile and its name without ext
json_path="$path.info.json" # path to json file with metadata created by youtube-dl
cue_path="$path.cue" # path to cue sheet to be generated
# echo -e "audio_path:\t$audio_path"
# echo -e "audio_file:\t$audio_file"
# echo -e "audio_name:\t$audio_name"
# echo -e "audio_ext:\t$audio_ext"
# echo -e "path:\t\t$path"
# echo -e "json_path:\t$json_path"
# echo -e "cue_path:\t$cue_path"
[ ! -f "$audio_path" ] && {
echo "ERROR: File not found: $audio_path"
exit 2
}
[ ! -f "$json_path" ] && {
echo "ERROR: File not found: $json_path"
exit 3
}
echo "PERFORMER `cat "$json_path" | jq -Mc '.channel'`" > "$cue_path"
echo "TITLE `cat "$json_path" | jq -Mc '.title'`" >> "$cue_path"
echo "FILE \"$audio_file\" ${audio_ext^^}" >> "$cue_path"
counter=1 # track counter (works only inside loop!)
cat "$json_path" | jq -Mc '.chapters[]' \
| while read chapter; do
number=`printf %0.2d $counter` # pad current counter with zeros
time=`echo "$chapter" | jq -Mc '.start_time'` # get initial start time in seconds
time=`printf '%0.2d:%0.2d:00' $((time/60)) $((time%60))` # convert start time to minutes:seconds
title=`echo "$chapter" | jq -Mc '.title' | sed -r "s#[\"]##g"` # get initial chapter title
performer=`echo "$title" | cut -d "-" -f 1 | sed 's#^[[:space:]]*##g' | sed 's# *$##g'` # get and trim chapter's performer (before '-')
title2=`echo "$title" | cut -d "-" -f 2 | sed 's#^[[:space:]]*##g' | sed 's# *$##g'` # get and trim chapter's title (after '-')
#TODO: what if dash is not delimiter between performer and title?
#TODO: take $title2 if $performer and (or?) $title2 are empty
printf "%-2sTRACK $number AUDIO\n" >> "$cue_path"
printf "%-4sPERFORMER \"$performer\"\n" >> "$cue_path"
printf "%-4sTITLE \"$title2\"\n" >> "$cue_path"
printf "%-4sINDEX 01 $time\n" >> "$cue_path"
counter=`expr $counter + 1` # increase counter
done
echo "Done! Cue file:"
echo "$cue_path"
| 1 | #!/bin/bash |
| 2 | # CUE-sheet generator for youtube-dl |
| 3 | |
| 4 | # Usage: |
| 5 | # 0. Install 'jq' utility |
| 6 | # 1. Download any audio file with metadata from YouTube or Youtube Music, e.g. |
| 7 | # $ youtube-dl \ |
| 8 | # --extract-audio \ |
| 9 | # --audio-format flac \ |
| 10 | # --audio-quality 0 \ |
| 11 | # --format bestaudio \ |
| 12 | # --write-info-json \ |
| 13 | # --output "/tmp/ytm/%(playlist_title)s/%(channel)s - %(title)s.%(ext)s" \ |
| 14 | # https://www.youtube.com/watch?v=lVpDQnXz34M |
| 15 | # |
| 16 | # If audio file is already downloaded earlier then just fetch only its metadata: |
| 17 | # $ youtube-dl \ |
| 18 | # --write-info-json \ |
| 19 | # --skip-download \ |
| 20 | # --output "/tmp/ytm/%(playlist_title)s/%(channel)s - %(title)s.%(ext)s" \ |
| 21 | # https://www.youtube.com/watch?v=lVpDQnXz34M |
| 22 | # |
| 23 | # 2. Audio and metadata files MUST be named exactly similar (except extenstion), |
| 24 | # but it is not necessary to keep original names. Also they MUST be placed in |
| 25 | # the same directory. Example: |
| 26 | # /tmp/ytm/ABGT496.flac |
| 27 | # /tmp/ytm/ABGT496.info.json |
| 28 | # |
| 29 | # 3. To create CUE file run ytdlcue with a path to audio file: |
| 30 | # $ ytdlcue.sh /tmp/ytm/ABGT496.flac |
| 31 | # |
| 32 | # A new file will be created in the same directory: |
| 33 | # /tmp/ytm/ABGT496.cue |
| 34 | |
| 35 | installed() { |
| 36 | command -v "$1" >/dev/null 2>&1 |
| 37 | } |
| 38 | |
| 39 | ! installed 'jq' && { |
| 40 | echo "ERROR: you need to install jq!" |
| 41 | exit 1 |
| 42 | } |
| 43 | |
| 44 | audio_path="$1" # path to audiofile |
| 45 | audio_file=`basename "$audio_path"` # audiofile name with extension |
| 46 | audio_name=${audio_file%.*} # audiofile name without extension |
| 47 | audio_ext=${audio_file##*.} # audiofile name extension |
| 48 | path="`dirname "$audio_path"`/$audio_name" # path to audiofile and its name without ext |
| 49 | json_path="$path.info.json" # path to json file with metadata created by youtube-dl |
| 50 | cue_path="$path.cue" # path to cue sheet to be generated |
| 51 | |
| 52 | # echo -e "audio_path:\t$audio_path" |
| 53 | # echo -e "audio_file:\t$audio_file" |
| 54 | # echo -e "audio_name:\t$audio_name" |
| 55 | # echo -e "audio_ext:\t$audio_ext" |
| 56 | # echo -e "path:\t\t$path" |
| 57 | # echo -e "json_path:\t$json_path" |
| 58 | # echo -e "cue_path:\t$cue_path" |
| 59 | |
| 60 | [ ! -f "$audio_path" ] && { |
| 61 | echo "ERROR: File not found: $audio_path" |
| 62 | exit 2 |
| 63 | } |
| 64 | [ ! -f "$json_path" ] && { |
| 65 | echo "ERROR: File not found: $json_path" |
| 66 | exit 3 |
| 67 | } |
| 68 | |
| 69 | echo "PERFORMER `cat "$json_path" | jq -Mc '.channel'`" > "$cue_path" |
| 70 | echo "TITLE `cat "$json_path" | jq -Mc '.title'`" >> "$cue_path" |
| 71 | echo "FILE \"$audio_file\" ${audio_ext^^}" >> "$cue_path" |
| 72 | |
| 73 | counter=1 # track counter (works only inside loop!) |
| 74 | cat "$json_path" | jq -Mc '.chapters[]' \ |
| 75 | | while read chapter; do |
| 76 | number=`printf %0.2d $counter` # pad current counter with zeros |
| 77 | time=`echo "$chapter" | jq -Mc '.start_time'` # get initial start time in seconds |
| 78 | time=`printf '%0.2d:%0.2d:00' $((time/60)) $((time%60))` # convert start time to minutes:seconds |
| 79 | title=`echo "$chapter" | jq -Mc '.title' | sed -r "s#[\"]##g"` # get initial chapter title |
| 80 | performer=`echo "$title" | cut -d "-" -f 1 | sed 's#^[[:space:]]*##g' | sed 's# *$##g'` # get and trim chapter's performer (before '-') |
| 81 | title2=`echo "$title" | cut -d "-" -f 2 | sed 's#^[[:space:]]*##g' | sed 's# *$##g'` # get and trim chapter's title (after '-') |
| 82 | #TODO: what if dash is not delimiter between performer and title? |
| 83 | #TODO: take $title2 if $performer and (or?) $title2 are empty |
| 84 | |
| 85 | printf "%-2sTRACK $number AUDIO\n" >> "$cue_path" |
| 86 | printf "%-4sPERFORMER \"$performer\"\n" >> "$cue_path" |
| 87 | printf "%-4sTITLE \"$title2\"\n" >> "$cue_path" |
| 88 | printf "%-4sINDEX 01 $time\n" >> "$cue_path" |
| 89 | |
| 90 | counter=`expr $counter + 1` # increase counter |
| 91 | done |
| 92 | echo "Done! Cue file:" |
| 93 | echo "$cue_path" |
| 94 |