From d2c835110f404546c3d558267bc10d87e735cc89 Mon Sep 17 00:00:00 2001 From: CoolnsX Date: Thu, 16 Jun 2022 23:34:34 +0530 Subject: [PATCH] feat: added script --- README.md | 15 +++++++++ hls | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100755 hls diff --git a/README.md b/README.md index 70d5495..5ed2321 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,17 @@ # hls_downloader + A posix compliant highly fast and efficient Asynchronous stable m3u8 links dowloader that uses shell jobs for controlling parallel download... + +# Increase Parallel Downloads.. + +Currently its set to my internet speed + +``` +Internet Speed = 12 MByte per seconds.. +36 (Internet Speed * 3).. +``` + +# Dependency + +- ffmpeg +- openssl diff --git a/hls b/hls new file mode 100755 index 0000000..52ae09e --- /dev/null +++ b/hls @@ -0,0 +1,95 @@ +#!/bin/sh + +#initializing.. + +help_text () { + while IFS= read -r line; do + printf "%s\n" "$line" + done <<-EOF + Usage: + ${0##*/} [ -f ] [ -s ] [ ] + ${0##*/} -h + + Options: + -h show helptext + -f filename (default : video) + -s select highest resolution automatically + EOF +} + +skip_res=0 +file="video" +tmpdir="${XDG_CACHE_HOME:-$HOME/.cache}/hls-temp" +jobdir="${XDG_CACHE_HOME:-$HOME/.cache}/hls-jobs" + +while getopts 'fs' OPT; do + case $OPT in + f) file=$OPTARG ;; + s) skip_res=1;; + *|h) + help_text + exit 0 + ;; + esac +done +shift $((OPTIND - 1)) + +[ -z "$*" ] && printf "\033[1;34mEnter link >\033[0m " && read -r link || link=$* +trap "rm -rdf $tmpdir $jobdir;exit 0" INT HUP +printf "\033[2K\r\033[1;36mFetching resolutions.." +m3u8_data=$(curl -s "$link") +res_list=$(printf "%s" "$m3u8_data" | sed -nE 's_.*RESOLUTION=.*x([^,]*),.*_\1_p') +highest_res=$(printf "$res_list" | sort -nr | head -1) +[ "$skip_res" -eq 1 ] && printf "\033[2K\r\033[1;36mSelecting highest resolution.." || (printf "" printf "\033[2K\r\033[1;33mRESOLUTIONS >>\n\033[0m$res_list\n\033[1;34mType ur preferred resolution (default: $highest_res) > " && read -r sel_res) +[ -z "$sel_res" ] && sel_res=$highest_res +unset highest_res res_list +url=$(printf "%s" "$m3u8_data" | sed -n "/$sel_res,/{n;p;}" | tr -d '\r') +[ -d "$tmpdir" ] || mkdir -p "$tmpdir" +#check whether the m3u8_data contains uri that starts from http +printf "%s" "$m3u8_data" | grep -q "http" || relative_url=$(printf "%s" "$link" | sed 's_[^/]*$__') +printf "\033[2K\r\033[1;36mFetching Metadata.." +resp="$(curl -s "${relative_url}$url")" +#extract key uri and iv uri from encrypted stream if exists.. +key_uri="$(printf "%s" "$resp" | sed -nE 's/^#EXT-X-KEY.*URI="([^"]*)"/\1/p')" +[ -z "$key_uri" ] || iv_uri="$(printf "%s" "$resp" | sed -nE 's/^#EXT-X-IV.*URI="([^"]*)"/\1/p')" +data="$(printf "%s" "$resp" | sed '/#/d')" +printf "%s" "$data" | grep -q "http" && relative_url='' || relative_url=$(printf "%s" "$link" | sed 's_[^/]*$__') +range=$(printf "%s\n" "$data" | wc -l) + +#for encrypted stream only +if [ -n "$key_uri" ];then + #extract key from uri.. + key=$(curl -s "$key_uri" | od -A n -t x1 | tr -d ' |\n') + #iv from uri + [ -z "$iv_uri" ] && iv=$(openssl rand -hex 16) || iv=$(curl -s "$iv_uri" | od -A n -t x1 | tr -d ' |\n') +fi + +printf "\033[2K\r\033[1;35mpieces : $range\n\033[1;33mDownloading.." +#downloading .ts data asynchronously +for i in $(seq $range); do + curl -s "${relative_url}$(printf "%s" "$data" | sed -n "${i}p")" > "$tmpdir/$(printf "%04d" "$i").ts" && printf "\033[2K\r\033[1;32m ✓ $i / $range done" & + jobs -p > "$jobdir" + while [ "$(cat "$jobdir" | wc -w)" -ge 35 ];do jobs > "$jobdir";sleep 0.05;done +done +wait + +#concatenating all .ts file in one file.. +if [ -n "$key_uri" ];then + #decrypting while concatenating.. + printf "\033[2K\r\033[1;36m Decrypting and Concatenating pieces into single file.." + for i in "$tmpdir"/*;do + cat "$i" | openssl aes-128-cbc -d -K "$key" -iv "$iv" -nopad >> "$file.ts" + done +else + printf "\033[2K\r\033[1;36m Concatenating pieces into single file.." + cat "$tmpdir"/* >> "$file.ts" +fi + +rm -rdf $tmpdir $jobdir +#conversion of allts file to mp4 video using ffmpeg.. +printf "\033[2K\r\033[1;36mEncoding file to mp4 video..\n\033[0m" +ffmpeg -i "$file.ts" -loglevel error -stats -c copy "$file.mp4" + +#cleanup.. +rm $file.ts +printf "\033[2K\r\033[1;36m Done!!"