Last active
October 23, 2025 03:21
-
-
Save YukariChiba/923d9e5beb432945615eb340be15866a to your computer and use it in GitHub Desktop.
netease-cloud-music-gtk export downloaded musics script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| function checkcmd() { | |
| cmdpkg=$1 | |
| [ -z "$2" ] || cmdpkg="$1 (in $2)" | |
| command -v $1 > /dev/null || { echo "error: $cmdpkg is required"; exit 1; } | |
| } | |
| checkcmd jq | |
| checkcmd file | |
| checkcmd magick ImageMagick | |
| checkcmd metaflac flac | |
| checkcmd ffmpeg | |
| checkcmd mid3v2 mutagen | |
| checkcmd bc | |
| checkcmd mediainfo | |
| cachedir=$(realpath ~/.cache/netease-cloud-music-gtk4) | |
| [ -d $cachedir ] || { echo "error: cache dir ($cachedir) not found"; exit 1; } | |
| destdir=$(realpath ~/Music/netease-cloud-music-gtk4) | |
| mkdir -p $destdir | |
| function musicextract() { | |
| m_meta=$1 | |
| m_id="$(jq -r '.id | select (.!=null)' $m_meta)" | |
| m_title="$(jq -r '.name | select (.!=null)' $m_meta)" | |
| m_artist="$(jq -r '.singer | select (.!=null)' $m_meta)" | |
| m_album="$(jq -r '.album | select (.!=null)' $m_meta)" | |
| m_album_id="$(jq -r '.album_id | select (.!=null)' $m_meta)" | |
| m_duration="$(jq -r '.duration | select (.!=null)' $m_meta)" | |
| m_pic_url="$(jq -r '.pic_url | select (.!=null)' $m_meta)" | |
| m_rate=$(find $cachedir -name "music_${m_id}_*" | rev | cut -f1 -d '_' | rev | sort -nr | head -n 1) | |
| m_file="$cachedir/music_${m_id}_${m_rate}" | |
| [ -f "$m_file" ] || return | |
| [ -z "$(find $destdir -name $m_id-$m_rate.*)" ] || return | |
| f_duration=$(mediainfo --Inform='Audio;%Duration%' $m_file) | |
| if [ "$f_duration" -lt "$m_duration" ]; then | |
| echo "Warning: skip potential partial music: $m_title - $m_album [$f_duration < $m_duration] ($m_album_id/$m_id)" | |
| return | |
| fi | |
| m_type="$(file -ib $m_file | cut -f1 -d ';')" | |
| m_pic=$(mktemp) | |
| curl -s $m_pic_url --output $m_pic | |
| m_pic_type=$(file -ib $m_pic | cut -f1 -d ';') | |
| if [ "$m_pic_type" == "image/png" ]; then | |
| magick -quiet $m_pic -quality 95% $m_pic.jpg | |
| m_pic=$m_pic.jpg | |
| m_pic_type=image/jpeg | |
| fi | |
| m_destdir="$destdir/${m_album_id}" | |
| mkdir -p $m_destdir | |
| m_dest="$m_destdir/$m_id-$m_rate" | |
| m_lrc="$cachedir/$m_id.tlrc" | |
| a_meta=$cachedir/album_$m_album_id.meta.json | |
| if [ -f $a_meta ]; then | |
| a_time="$(jq -r '.publish_time | select (.!=null)' $a_meta)" | |
| a_time="$(date -d @$(echo "$a_time / 1000" | bc) +%Y-%m-%d)" | |
| a_artist="$(jq -r '.artist_name | select (.!=null)' $a_meta)" | |
| m_order="$(jq -r ".songs | map(.id == $m_id) | index(true) | select (.!=null) + 1" $a_meta)" | |
| fi | |
| case $m_type in | |
| "audio/flac") | |
| m_dest=$m_dest.flac | |
| cp $m_file $m_dest | |
| metaflac \ | |
| --set-tag=ALBUM="$m_album" \ | |
| --set-tag=ARTIST="$m_artist" \ | |
| --set-tag=TITLE="$m_title" \ | |
| --import-picture-from="|$m_pic_type|||$m_pic" \ | |
| $m_dest > /dev/null | |
| [ ! -f $a_meta ] || \ | |
| metaflac \ | |
| --set-tag=ALBUMARTIST="$a_artist" \ | |
| --set-tag=TRACKNUMBER="$m_order" \ | |
| --set-tag=DATE="$a_time" \ | |
| $m_dest > /dev/null | |
| [ ! -f $m_lrc ] || \ | |
| metaflac \ | |
| --set-tag-from-file=LYRICS=$m_lrc \ | |
| $m_dest > /dev/null | |
| ;; | |
| "audio/mpeg") | |
| [ ! -f $m_lrc ] || cp $m_lrc $m_dest.lrc | |
| m_dest=$m_dest.mp3 | |
| cp $m_file $m_dest | |
| mid3v2 -a "$m_artist" -t "$m_title" -A "$m_album" -p $m_pic $m_dest > /dev/null | |
| [ ! -f $a_meta ] || \ | |
| mid3v2 --TPE2 "$a_artist" -T "$m_order" --date "$a_time" $m_dest > /dev/null | |
| ;; | |
| esac | |
| echo "New song added: $m_title - $m_album [$m_type] ($m_album_id/$m_id)" | |
| } | |
| export -f musicextract | |
| export cachedir destdir | |
| find $cachedir -name "music_*.meta.json" | xargs -P 4 -I @ bash -c "musicextract @" | |
| echo "Done!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment