ytdlcue.sh(файл создан)
| @@ -0,0 +1,93 @@ | |||
| 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" | |
Новее
Позже