Skip to content

Instantly share code, notes, and snippets.

@BenjaminPoncet
Last active March 29, 2024 10:11
Show Gist options
  • Save BenjaminPoncet/bbef9edc1d0800528813e75c1669e57e to your computer and use it in GitHub Desktop.
Save BenjaminPoncet/bbef9edc1d0800528813e75c1669e57e to your computer and use it in GitHub Desktop.
Synology VideoStation ffmpeg wrapper with DTS, EAC3 and TrueHD support. This project is no longer maintained: Please see the following projects: https://github.com/darknebular/Wrapper_VideoStation/ - https://github.com/AlexPresso/VideoStation-FFMPEG-Patcher
#!/bin/bash
rev="12"
_log(){
echo "$(date '+%Y-%m-%d %H:%M:%S') - ${streamid} - $1" >> /tmp/ffmpeg.log
}
_log_para(){
echo "$1" | fold -w 120 | sed "s/^.*$/$(date '+%Y-%m-%d %H:%M:%S') - ${streamid} - = &/" >> /tmp/ffmpeg.log
}
_term(){
rm /tmp/ffmpeg-${streamid}.stderr
_log "*** KILLCHILD ***"
kill -TERM "$childpid" 2>/dev/null
}
trap _term SIGTERM
arch=`uname -a | sed 's/.*synology_//' | cut -d '_' -f 1`
nas=`uname -a | sed 's/.*synology_//' | cut -d '_' -f 2`
pid=$$
paramvs=$@
stream="${@: -1}"
streamid="FFM$pid"
bin1=/var/packages/ffmpeg/target/bin/ffmpeg
bin2=/var/packages/VideoStation/target/bin/ffmpeg.orig
args=()
vcodec="KO"
while [[ $# -gt 0 ]]
do
case "$1" in
-i)
shift
movie="$1"
args+=("-i" "$1")
;;
-hwaccel)
shift
hwaccel="$1"
args+=("-hwaccel" "$1")
;;
-scodec)
shift
scodec="$1"
args+=("-scodec" "$1")
;;
-f)
shift
fcodec="$1"
args+=("-f" "$1")
;;
-map)
shift
args+=("-map" "$1")
idmap=`echo $1 | cut -d : -f 2`
if [ "$vcodec" = "KO" ]; then
vcodec=`/var/packages/ffmpeg/target/bin/ffprobe -v error -select_streams $idmap -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$movie" | head -n 1`
vcodecprofile=`/var/packages/ffmpeg/target/bin/ffprobe -v error -select_streams $idmap -show_entries stream=profile -of default=noprint_wrappers=1:nokey=1 "$movie" | head -n 1`
else
acodec=`/var/packages/ffmpeg/target/bin/ffprobe -v error -select_streams $idmap -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$movie" | head -n 1`
fi
;;
*)
args+=("$1")
;;
esac
shift
done
_log "*** PROCESS START REV $rev DS$nas ($arch) PID $pid ***"
streamdir=`dirname "$stream"`
device=`cat ${streamdir}/video_metadata | jq -r '.device'`
_log "DEVICE = $device"
_log "MOVIE = $movie"
set -- "${args[@]}"
argsnew=()
args1sv=()
args2sv=()
args1vs=()
args2vs=()
while [[ $# -gt 0 ]]
do
case "$1" in
-ss)
shift
argsnew+=("-ss" "$1")
args1sv+=("-ss" "$1")
args1sv+=("-noaccurate_seek")
args1vs+=("-ss" "$1")
args1vs+=("-noaccurate_seek")
args2sv+=("-analyzeduration" "10000000")
args2vs+=("-analyzeduration" "10000000")
;;
-i)
shift
argsnew+=("-i" "$1")
args1sv+=("-i" "$1")
args2sv+=("-i" "pipe:0" "-map" "0")
args1vs+=("-i" "$1")
args2vs+=("-i" "pipe:0" "-map" "0")
;;
-vf)
shift
if [ "$hwaccel" = "vaapi" ] && [ "$vcodecprofile" = "Main 10" ]; then
scale_w=`echo "${1}" | sed -e 's/.*=w=//g' | sed -e 's/:h=.*//g'`
scale_h=`echo "${1}" | sed -e 's/.*:h=//g'`
if let ${scale_w} AND let ${scale_h}; then
argsnew+=("-vf" "scale_vaapi=w=${scale_w}:h=${scale_h}:format=nv12,hwupload,setsar=sar=1")
else
argsnew+=("-vf" "scale_vaapi=format=nv12,hwupload,setsar=sar=1")
fi
else
argsnew+=("-vf" "$1")
fi
args2sv+=("-vf" "$1")
args1vs+=("-vf" "$1")
;;
-vcodec)
shift
argsnew+=("-vcodec" "$1")
args1sv+=("-vcodec" "copy")
args2sv+=("-vcodec" "$1")
args1vs+=("-vcodec" "$1")
args2vs+=("-vcodec" "copy")
;;
-acodec)
shift
if [ "$1" = "libfaac" ]; then
argsnew+=("-acodec" "aac")
args1sv+=("-acodec" "aac")
args2vs+=("-acodec" "aac")
else
argsnew+=("-acodec" "$1")
args1sv+=("-acodec" "$1")
args2vs+=("-acodec" "$1")
fi
args2sv+=("-acodec" "copy")
args1vs+=("-acodec" "copy")
;;
-ab)
shift
argsnew+=("-ab" "$1")
args1sv+=("-ab" "$1")
args2vs+=("-ab" "$1")
;;
-ac)
shift
argsnew+=("-ac" "$1")
args1sv+=("-ac" "$1")
args2vs+=("-ac" "$1")
;;
-f)
shift
argsnew+=("-f" "$1")
args1sv+=("-f" "mpegts")
args2sv+=("-f" "$1")
args1vs+=("-f" "mpegts")
args2vs+=("-f" "$1")
;;
-segment_format)
shift
argsnew+=("-segment_format" "$1")
args2vs+=("-segment_format" "$1")
args2sv+=("-segment_format" "$1")
;;
-segment_list_type)
shift
argsnew+=("-segment_list_type" "$1")
args2vs+=("-segment_list_type" "$1")
args2sv+=("-segment_list_type" "$1")
;;
-hls_seek_time)
shift
argsnew+=("-hls_seek_time" "$1")
args2vs+=("-hls_seek_time" "$1")
args2sv+=("-hls_seek_time" "$1")
;;
-segment_time)
shift
argsnew+=("-segment_time" "$1")
args2vs+=("-segment_time" "$1")
args2sv+=("-segment_time" "$1")
;;
-segment_time_delta)
shift
argsnew+=("-segment_time_delta" "$1")
args2vs+=("-segment_time_delta" "$1")
args2sv+=("-segment_time_delta" "$1")
;;
-segment_start_number)
shift
argsnew+=("-segment_start_number" "$1")
args2vs+=("-segment_start_number" "$1")
args2sv+=("-segment_start_number" "$1")
;;
-individual_header_trailer)
shift
argsnew+=("-individual_header_trailer" "$1")
args2vs+=("-individual_header_trailer" "$1")
args2sv+=("-individual_header_trailer" "$1")
;;
-avoid_negative_ts)
shift
argsnew+=("-avoid_negative_ts" "$1")
args2vs+=("-avoid_negative_ts" "$1")
args2sv+=("-avoid_negative_ts" "$1")
;;
-break_non_keyframes)
shift
argsnew+=("-break_non_keyframes" "$1")
args2vs+=("-break_non_keyframes" "$1")
args2sv+=("-break_non_keyframes" "$1")
;;
-max_muxing_queue_size)
shift
args2vs+=("-max_muxing_queue_size" "$1")
args2sv+=("-max_muxing_queue_size" "$1")
;;
-map)
shift
argsnew+=("-map" "$1")
args1sv+=("-map" "$1")
args1vs+=("-map" "$1")
;;
*)
argsnew+=("$1")
if [ "$stream" = "$1" ]; then
args1sv+=("-bufsize" "1024k" "pipe:1")
args2sv+=("$1")
args1vs+=("-bufsize" "1024k" "pipe:1")
args2vs+=("$1")
else
args2sv+=("$1")
args1vs+=("$1")
fi
;;
esac
shift
done
sed -i -e "s/{\"PID\":${pid},\"hardware_transcode\":true,/{\"PID\":${pid},\"hardware_transcode\":false,/" /tmp/VideoStation/enabled
startexectime=`date +%s`
if [ "$scodec" = "subrip" ]; then
_log "FFMPEG = $bin2"
_log "CODEC = $scodec"
_log "PARAMVS ="
_log_para "$paramvs"
$bin2 "${args[@]}" &> /tmp/ffmpeg-${streamid}.stderr &
elif [ "$fcodec" = "mjpeg" ]; then
_log "FFMPEG = $bin2"
_log "CODEC = $fcodec"
_log "PARAMVS ="
_log_para "$paramvs"
$bin2 "${args[@]}" &> /tmp/ffmpeg-${streamid}.stderr &
else
_log "VCODEC = $vcodec ($vcodecprofile)"
_log "ACODEC = $acodec"
_log "PARAMVS ="
_log_para "$paramvs"
_log "MODE = WRAP"
_log "FFMPEG = $bin1"
_log "PARAMWP ="
param1=${argsnew[@]}
_log_para "$param1"
$bin1 "${argsnew[@]}" &> /tmp/ffmpeg-${streamid}.stderr &
fi
childpid=$!
_log "CHILDPID = $childpid"
wait $childpid
if grep "Conversion failed!" /tmp/ffmpeg-${streamid}.stderr || grep "Error opening filters!" /tmp/ffmpeg-${streamid}.stderr || grep "Unrecognized option" /tmp/ffmpeg-${streamid}.stderr || grep "Invalid data found when processing input" /tmp/ffmpeg-${streamid}.stderr; then
_log "*** CHILD END ***"
startexectime=`date +%s`
_log "STDOUT ="
_log_para "`tail -n 15 /tmp/ffmpeg-${streamid}.stderr`"
_log "MODE = PIPE SV"
_log "FFMPEG1 = $bin1"
_log "FFMPEG2 = $bin2"
_log "PARAM1 ="
param1=${args1sv[@]}
_log_para "$param1"
_log "PARAM2 ="
param2=${args2sv[@]}
_log_para "$param2"
$bin1 "${args1sv[@]}" | $bin2 "${args2sv[@]}" &> /tmp/ffmpeg-${streamid}.stderr &
childpid=$!
_log "CHILDPID = $childpid"
wait $childpid
fi
if grep "Conversion failed!" /tmp/ffmpeg-${streamid}.stderr || grep "Error opening filters!" /tmp/ffmpeg-${streamid}.stderr || grep "Unrecognized option" /tmp/ffmpeg-${streamid}.stderr || grep "Invalid data found when processing input" /tmp/ffmpeg-${streamid}.stderr; then
_log "*** CHILD END ***"
startexectime=`date +%s`
_log "STDOUT ="
_log_para "`tail -n 15 /tmp/ffmpeg-${streamid}.stderr`"
_log "MODE = PIPE VS"
_log "FFMPEG1 = $bin2"
_log "FFMPEG2 = $bin1"
_log "PARAM1 ="
param1=${args1vs[@]}
_log_para "$param1"
_log "PARAM2 ="
param2=${args2vs[@]}
_log_para "$param2"
$bin2 "${args1vs[@]}" | $bin1 "${args2vs[@]}" &> /tmp/ffmpeg-${streamid}.stderr &
childpid=$!
_log "CHILDPID = $childpid"
wait $childpid
fi
if grep "Conversion failed!" /tmp/ffmpeg-${streamid}.stderr || grep "Error opening filters!" /tmp/ffmpeg-${streamid}.stderr || grep "Unrecognized option" /tmp/ffmpeg-${streamid}.stderr || grep "Invalid data found when processing input" /tmp/ffmpeg-${streamid}.stderr; then
_log "*** CHILD END ***"
startexectime=`date +%s`
_log "STDOUT ="
_log_para "`tail -n 15 /tmp/ffmpeg-${streamid}.stderr`"
_log "MODE = ORIG"
_log "FFMPEG = $bin2"
$bin2 "${args[@]}" &> /tmp/ffmpeg-${streamid}.stderr &
childpid=$!
_log "CHILDPID = $childpid"
wait $childpid
fi
stopexectime=`date +%s`
if test $((stopexectime-startexectime)) -lt 10; then
_log "STDOUT ="
_log_para "`tail -n 15 /tmp/ffmpeg-${streamid}.stderr`"
fi
_log "*** CHILD END ***"
_log "*** PROCESS END ***"
rm /tmp/ffmpeg-${streamid}.stderr
@darknebular
Copy link

darknebular commented Aug 11, 2023

THESE ARE OBJECTIVE FACTS AND NOT "FEELINGS OR THE LIKE": THE TRUTH ONLY

The 12.2 was launched in April 2021: (Version 12.1 was even earlier than that date)
image

I asked you up to 3 times to at least mention me and I asked you please, you laughed at my improvements and copied all my first versions and improvements made on Benjamin's wrapper and then you said you didn't.
image

image

### I changed the binaries order in 12.1, delete some commands, fix the logging in order to have only error output and not all output, change the names in the methods with more logical names, you Copy-Paste ALL my changes and ALL my wrapper's fixes or Versions without mention to me and now you are crying because I did a fork from your Simplest? At least I mention to you into the Simplest's wrapper.

LEFT IT'S MY INITIAL WRAPPER'S VERSION 12.1, RIGHT IT'S THE DEPRECATED BENJAMIN'S WRAPPER 12 VERSION.
image
image
image

Here "Alex's" wrapper "from" the "Benjamin's one", but It was really a Copy-Paste from MY INITIAL VERSION 12.1:

image
image
image

I know why I put this 22 there, you don't.

Could you explain this 22 there? No, You can't do it. UP TO THE LAST COMMA, IT WAS AN EXACT COPY PASTE

@txsastre
Copy link

txsastre commented Aug 11, 2023

Eso, que yo también quiero birra. Ánimos @darknebular , buen trabajo.

❤❤❤❤❤❤❤❤❤❤ OEEE MUCHAS GRACIAS!! Tú también eres o hablas español? Para ti también por su puesto... Espero que ahora no coja y diga que tu cuenta soy yo también que me auto-escribo dice jajajaja, como ha dicho de las otras 2 cuentas anteriores...xD

Sólo tengo esta cuenta y hoy casi la pierdo por entrar al trapo con él. Supongo que él lo hará y por eso lo ve factible que yo también lo haga.

Saludos.

#################

For you too, of course... I hope that now he doesn't pick up and say that your account is also me who writes myself, he says hahahaha, as he said about the other 2 previous accounts... xD

I only have this account and today I almost lost it for going to the rag with him. I suppose that he will do it and that is why he sees it feasible that I do it too.

Greetings.

From Spain.
I have to say that is sort of sad to see this kind of discussion here, in a place that open source means "sharing".

I've used both and both do the trick for me, be able to see movies.

Don't waste your time fighting each other, I'm very grateful for your work and the time you have spend for developing this and sharing your knowledge.

And no, I'm not "darknebuka*, I work as system admin and networks, I left behind development.

Now I'm using @darknebular and sometimes ask if it's possible to see subtitles xD. (Yes you said the problem is Synology).

Please peace here.

@darknebular
Copy link

Peace!!!

@geoff2k
Copy link

geoff2k commented Aug 11, 2023

I wish you all could harness this energy and channel it into something productive.

This clearly is something you are both passionate about, but the negativity that this is bringing into your lives can't be worth it.

@AlexPresso
Copy link

Peace

@kalety
Copy link

kalety commented Aug 12, 2023 via email

@darknebular
Copy link

Hi guys, it will be possible “Things” like HDR, 4K, etc in our loved Sinologys?
image
image
image
image

I think that YES!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment