#!/bin/bash # .env contains a line like # BASE64_BEARER_TOKEN='' # Retrieve that base64 token from a request from the browser # network tab network tabfrom a logged in MS Stream (Classic) tab source .env OUTDIR="./videos" read -r -d '' API_URL <<- 'EOM' https://euwe-1.api.microsoftstream.com/api/videos? $top=100 & $skip=0 & $orderby=metrics/trendingScore asc & $filter= published{SPACE} and{SPACE} ( ( state eq 'Completed' and contentSource ne 'livestream' ){SPACE} or{SPACE} ( contentSource eq 'livestream'{SPACE} and not ( state eq 'Completed'{SPACE} and not liveEvent/LiveEventOptions/OnDemandOptions/EnablePlayback ) ) ) & api-version=1.4-private EOM API_URL="$(tr -d -- '\n' <<< "${API_URL//\{SPACE\}/ }")" mkdir -p "${OUTDIR}" || { printf '\033[31m%s\033[m\n' 'Aborting' exit 2 } # '>' without quotes is delimiter, since it's one of the few chars disallowed in a URL. Title must not include this char # https://www.ietf.org/rfc/rfc2396.txt # 2.4.3. Excluded US-ASCII Characters m3u8_manifest_urls_and_metadata=$( # shellcheck disable=SC2312 wget --no-verbose --quiet -O- --header="authorization: Bearer ${BASE64_BEARER_TOKEN}" "${API_URL}" | jq -r '.value[] | .name + ">" + .media.duration[2:] + ">" + (.playbackUrls | map(select(.mimeType == "application/vnd.apple.mpegurl")) | .[].playbackUrl)' ) [[ -z "${m3u8_manifest_urls_and_metadata}" ]] && { printf '\033[31m%s\033[m\n' 'Error GETting manifest urls (response empty) or Bearer token invalid/expired. Exiting.' exit 3 } idx=1 total="$(wc -l <<< "${m3u8_manifest_urls_and_metadata}")" IFS=$'\n' for m3u8_manifest_url_and_metadata in ${m3u8_manifest_urls_and_metadata}; do IFS='>' read -r title length m3u8_manifest_url <<< "${m3u8_manifest_url_and_metadata}" length="$(sed -e 's/\..*S/S/g' -e 's/M/:/g' -e 's/H/:/g' <<< "${length}")" filepath="${OUTDIR}/${title}.mp4" printf '\033[32m%s\033[m\n' "Download '${filepath}' (${idx}/${total})" # shellcheck disable=SC2312 ffmpeg -hide_banner \ -loglevel error \ -headers "authorization: Bearer ${BASE64_BEARER_TOKEN}" \ -i "${m3u8_manifest_url}" \ -progress - \ -codec copy \ "${filepath}" | grep --line-buffered 'out_time=' | sed -u -e 's/out_time=//g' -e 's/\..*//g' -e 's/^-//g' | xargs -I{} printf "{} of ${length} \r" printf '\n\033[33m%s\033[m\n' "Done" idx=$(( idx + 1 )) done