diff --git a/video-convert b/video-convert deleted file mode 100755 index b98c547..0000000 --- a/video-convert +++ /dev/null @@ -1,281 +0,0 @@ -#!/bin/bash -# Look into HW video encoding to vp9 instead of h264: -# https://www.reddit.com/r/VP9/comments/g9uzzv/hardware_encoding_vp9_on_intel/ - -log_file="" - -force=0 -if [[ "$1" == "-f" ]]; then - force=1 - shift -fi - -fail() { - echo "$*" >&2 - if [[ -e ${log_file} ]]; then - rm ${log_file} - fi - exit -1 -} - -VIDEO=$(getent group video | sed -E 's,^video:[^:]*:([^:]*):.*$,\1,') -RENDER=$(getent group render | sed -E 's,^render:[^:]*:([^:]*):.*$,\1,') - -[[ "${VIDEO}" != "" ]] || fail "No video group found." - -ADD_GROUPS="--group-add ${VIDEO}" -[[ "${RENDER}" != "" ]] && ADD_GROUPS+=" --group-add ${RENDER}" - -video_detect() { - for file in "${*}"; do - INFO=($(ffprobe -v error \ - -select_streams v:0 \ - -show_entries stream=codec_name:format=format_name \ - -of default=noprint_wrappers=1:nokey=1 "${file}")) - if (( ${#INFO[*]} != 2 )); then - echo "${file}|none|none" - else - echo "${file}|${INFO[0]}|${INFO[1]}" - fi - done -} - -# mstodate MILLISECONDS -# -# Given MILLISECONDS, convert to DAYS:HOURS:MINUTES:SECONDS.MS -mstodate() { - scales=( "86400-d:" "3600-h:-02" "60-m:-02" "1-.-02" ) - echo $1 | sed -E 's/([[:digit:]]{3})$/ \1/' | while read sec msec; do - for scale in ${scales[@]}; do - parts=(${scale//-/ }) - divisor=${parts[0]} - suffix=${parts[1]} - min=${parts[2]} - num_scale=$((sec / divisor)) - sec=$((sec - (num_scale * divisor))) - printf "%${min}d%s" ${num_scale} ${suffix} - done - echo "${msec}s" - done -} - -function move_to_backup { - IN="$1" - base="$(dirname "${IN}")" - if [ ! -d "${base}" ]; then - continue - fi - base=/multimedia/backup"${base}" - if [ ! -d "${base}" ]; then - mkdir -p "${base}" || fail "Unable to mkdir '${base}'" - fi - if [ -d "${base}" ]; then - mv "${IN}" "${base}"/ || fail "Unable to move '$IN'" - fi -} - -function convert { - IN="$1" - SRC_CODEC="$2" - FORMAT="$3" - current="$4" - total="$5" - IN="$(realpath "${IN}")" - OUT="${IN/%.???/.mkv}" - ORIG="${OUT}" - if [[ "${OUT}" == "${IN}" ]]; then - OUT="${OUT/.mkv/.transcoded.mkv}" - fi - - width=0 - eval $(ffprobe -v error -show_entries 'stream=width' -select_streams v "${IN}" | grep width) - if (( width == 0 )); then - fail "Unable to determine width of ${IN}" - fi - if (( width > 1920 )); then - echo "Limiting width to 1920" - width=1920 - fi - - TITLE="${IN%.*}" - TITLE="${TITLE##*/}" - if [[ "${SRC_CODEC}" == "h264" ]]; then - if (( force == 1 )); then - input_flags=" - -hwaccel qsv - " -# HW decode here gives a MXF device error. Not sure why. -# -c:v h264_qsv - output_flags=" - -c copy - -c:v h264_qsv - -vf hwupload=extra_hw_frames=64 - -vf vpp_qsv=format=nv12,scale_qsv=w=${width} - -global_quality 20 - " - else - echo "${current}/${total}: Content will have format changed from ${FORMAT}/h264 to mkv/h264." - # Just change container to matroska - input_flags=" - " - output_flags=" - -c copy - " - fi - else - echo "${current}/${total}: Content will be transcoded from ${FORMAT}/${SRC_CODEC} to mkv/h264." - # Convert all video streams to h264. Copy all other streams unchanged (audio, subtitle, etc.) - # Move headers to start of the file for fast start - # Use "reasonable" quality level of 20, slow encode - # - input_flags=" - -hwaccel qsv - -c:v hevc_qsv - " - output_flags=" - -c copy - -vf vpp_qsv=format=nv12,scale_qsv=${width} - -c:v h264_qsv - -global_quality 20 - " - fi - - echo -n "${current}/${total}: Counting frames in ${IN}: " - FRAMES=$(ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 "${IN}") || fail "Unable to count frames" - echo "${current}/${total}: ${FRAMES} frames." - - if [[ "${ORIG}" != "${OUT}" ]]; then - echo "${current}/${total}: Output file will be $(basename "${OUT}")." - fi - - # Use stdbuf to flush stdout/stderr every line - STARTTIME=$(date +%s) - LASTTIME=${STARTTIME} - LASTPOS=0 - DIN="$(dirname "${IN}")" - DOUT="$(dirname "${OUT}")" - quiet=" - -v quiet - -loglevel error - " -# quiet="" - - log_file=$(mktemp) - { - docker run \ - --device=/dev/dri \ - --user=$(id -u) \ - --rm \ - ${ADD_GROUPS} \ - -v "${DIN}":"${DIN}" \ - -v "${DOUT}":"${DOUT}" \ - intel-media-ffmpeg \ - ffmpeg \ - ${quiet} \ - -nostdin \ - ${input_flags} \ - -i "${IN}" \ - -progress /dev/stdout \ - -metadata title="${TITLE/.\//}" \ - ${output_flags} \ - -movflags +faststart \ - "${OUT}" \ - -y || { echo "FFMPEG failed" | tee ${log_file} ; false ; } - } | while read line; do - if [[ "${line}" == "FFMPEG failed" ]]; then - cat ${log_file} - fail "Terminating" - false - break - fi - POS=$(echo $line | sed -n 's/^frame=*\(.*\)/\1/p') - if [[ "${POS}" == "" ]]; then - true - continue - fi - - NOW=$(date +%s) - ELAPSEDTIME=$(( NOW - LASTTIME )) - if (( ELAPSEDTIME <= 5 )); then - true - continue - fi - - ELAPSEDFRAMES=$(( POS - LASTPOS )) - REMAININGFRAMES=$(( FRAMES - POS )) - REMAININGFRAMES=$(( REMAININGFRAMES * 1000 )) # convert to ms - FRAMERATE=$(( ELAPSEDFRAMES / ELAPSEDTIME )) - if (( FRAMERATE != 0 )); then - REMAININGMS=$(( REMAININGFRAMES / FRAMERATE )) - printf "\r%*s\r%s" $(tput cols) " " "${current}/${total}: $(mstodate $(( NOW - STARTTIME ))000). Transcode $((ELAPSEDFRAMES / ELAPSEDTIME ))fps. Frame $POS of $FRAMES $(( $(( 100 * POS)) / FRAMES ))%. ETA $(mstodate ${REMAININGMS}) remaining." - else - printf "\r%*s\r%s" $(tput cols) " " "${current}/${total}: $(mstodate $(( NOW - STARTTIME ))000). Transcode $((ELAPSEDFRAMES / ELAPSEDTIME ))fps. Frame $POS of $FRAMES $(( $(( 100 * POS)) / FRAMES ))%. No frames processed in last ${ELAPSEDTIME} seconds." - fi - LASTTIME=${NOW} - LASTPOS=${POS} - done || fail 'Unable to transcode' - - if grep -q "FFMPEG failed" ${log_file}; then - exit -1 - fi - - move_to_backup "${IN}" - - if [[ "${ORIG}" == "${IN}" ]]; then - # If the original file was an '.mkv' then OUT was '.transcoded.mkv' - # during transcode. Now that the transcode is complete, set the - # file back to the original name. - mv "${OUT}" "${IN}" || fail "Unable to mv '${OUT}' -> '${IN}'" - fi - - rm ${log_file} - NOW=$(date +%s) - echo -e "\n${current}/${total}: Completed in $(mstodate $(( NOW - STARTTIME ))000)" -} - -function check_and_convert { - current="$2" - total="$3" - video_detect "$1" | while read entry; do - # # file:codec:format - file="${entry%%|*}" # file - entry="${entry#*|}" # codec:format - codec="${entry%%|*}" # codec - format="${entry##*|}" # format - codec="${codec,,}" - if [[ "${codec}" == "none" ]]; then - continue - fi - if (( force == 0 )) && [[ "${codec}" == "h264" ]] && [[ "${format}" =~ mkv|matroska ]]; then - # If container is not mkv, convert to mkv container - echo "${current}/${total}: Skipping ${file} as it is already mkv/h264." - else - convert "${file}" "${codec}" "${format}" "$current" "$total" - fi - done -} - -if [ -z "$1" ]; then - find . -name '* *' -type d | while read file; do mv "${file}" "${file// /_}" || fail "Unable to rename dir ${file}"; done - find . -name '* *' -type f | while read file; do mv "${file}" "${file// /_}" || fail "Unable to rename file ${file}"; done - total=$(find . -type f \ - -and -not -path "./backup/*" | wc -l) - current=0 - find . -type f \ - -and -not -path "./backup/*" | sort | while read file; do - check_and_convert "${file}" ${current} ${total} - current=$((current+1)) - done -else - for file in "$*"; do - check_and_convert "${file}" 1 1 - done -fi && { - cat << EOF -To transfer the updated files: - -rsync -avprlP --remove-source-files /multimedia/Downloads/ azurite:/multimedia/ -find /multimedia/Downloads/ -type d -empty -delete - -EOF -}