Skip to content

Instantly share code, notes, and snippets.

@mostlyfine
Last active May 17, 2024 00:38
Show Gist options
  • Save mostlyfine/88bc1c8838bb726b9546130a4afd8d41 to your computer and use it in GitHub Desktop.
Save mostlyfine/88bc1c8838bb726b9546130a4afd8d41 to your computer and use it in GitHub Desktop.
NHK Radio Streaming download script.
#!/bin/bash
# require
# - curl
# - jq
# - ffmpeg
if [ $# -ne 1 ]; then
echo "usage) $0 <site_id>"
echo " ex) $0 0916"
echo ""
echo "site_id title"
echo "6805: 小学生の基礎英語"
echo "6806: 中学生の基礎英語 レベル1"
echo "6807: 中学生の基礎英語 レベル2"
echo "6808: 中高生の基礎英語 in English"
echo "0916: ラジオ英会話"
echo "4121: ボキャブライダー"
echo "3064: エンジョイ・シンプル・イングリッシュ"
echo "2331: 英会話タイムトライアル"
echo "7512: ニュースで学ぶ「現代英語」"
echo "6809: ラジオビジネス英語"
echo "0915: まいにち中国語"
echo "6581: ステップアップ中国語"
echo "0951: まいにちハングル講座"
echo "6810: ステップアップ ハングル講座"
echo "0946: まいにちイタリア語 初級編・応用編"
echo "0943: まいにちドイツ語 初級編・応用編"
echo "0953: まいにちフランス語 初級編・応用編"
echo "0948: まいにちスペイン語 初級編・応用編"
echo "0956: まいにちロシア語 初級編・応用編"
echo "0937: アラビア語講座"
echo "2769: ポルトガル語講座"
exit 1
fi
max_retry_count=3
retry_interval=5
site_id=$1
corner_site_id=${2:-01}
tmpfile=$(mktemp)
function rm_tmpfile {
[[ -f "${tmpfile}" ]] && rm -f "$tmpfile"
}
trap rm_tmpfile EXIT
trap 'trap - EXIT; rm_tmpfile; exit -1' INT PIPE TERM
url="https://www.nhk.or.jp/radio-api/app/v1/web/ondemand/series?site_id=${site_id}&corner_site_id=${corner_site_id}"
curl -Ls ${url} > ${tmpfile}
read lesson series_url thumbnail_url <<< $(cat ${tmpfile} | jq -r '[.title, .series_url, .thumbnail_url] | join(" ")')
mkdir -p ${lesson}
echo "${lesson} downloading."
cat $tmpfile | jq -c '.episodes[]' | while read -r episode; do
program_title=$(echo "${episode}" | jq -r '.program_title'| cut -d " " -f 2)
stream_url=$(echo "${episode}" | jq -r '.stream_url')
year=$(echo "${episode}" | jq -r '.aa_contents_id' | cut -f 4 -d ';' | cut -b 1-4)
month=$(echo "${episode}" | jq -r '.aa_contents_id' | cut -f 4 -d ';' | cut -b 5-6)
day=$(echo "${episode}" | jq -r '.aa_contents_id' | cut -f 4 -d ';' | cut -b 7-8)
filename="${lesson}/${lesson}-${year}-${month}-${day}.mp3"
echo "download start: ${program_title}"
if [[ -e ${filename} ]]; then
echo "${filename} is exists."
else
while true; do
ffmpeg -hide_banner -http_seekable 0 -n -i "${stream_url}" -i "${thumbnail_url}" \
-map 0 -map 1 \
-id3v2_version 3 \
-metadata title="${year}-${month}-${day} ${program_title}" \
-metadata album="${lesson}" \
-metadata date="${year}-${month}-${day}" \
-metadata artist=NHK \
-metadata copyright=NHK \
-t 15:00 \
-c:a mp3 \
-loglevel error \
${filename} </dev/null && break
retry_count=$((retry_count + 1))
[ ${retry_count} -eq ${max_retry_count} ] && break
echo "download failed. retry ${retry_count}"
sleep ${retry_interval}
done
if [ -s $filename ] && [ $DROPBOX_REFRESH_TOKEN ] && [ $DROPBOX_APP_KEY ] && [ $DROPBOX_APP_SECRET ]; then
echo "upload dropbox"
API_TOKEN=$(curl -LSs https://api.dropbox.com/oauth2/token \
-d grant_type=refresh_token \
-d refresh_token=${DROPBOX_REFRESH_TOKEN} \
-u ${DROPBOX_APP_KEY}:${DROPBOX_APP_SECRET} | jq -r .access_token)
curl -LSs -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer ${API_TOKEN}" \
--header "Dropbox-API-Arg: {\"path\": \"/$filename\",\"mode\": \"overwrite\",\"autorename\": false,\"mute\": false}" \
--header "Content-Type: application/octet-stream" \
--data-binary @${filename} | jq -r .
fi
sleep 10
fi
done
# FYI:
# - https://github.com/ikakunsan/radio-gogaku-downloader
# - https://simplelife.pgw.jp/it/nhk_radio_gogaku_kouza_json/
# - https://kazkn.com/post/2017/bash-loop-ffmpeg/
# - https://wiki.multimedia.cx/index.php/FFmpeg_Metadata#MP3
# - https://qiita.com/tksnino/items/bcbde6eddcb553446f63
# - https://zenn.dev/yakumo/articles/75d3df651d0609
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment