From 069340e20a9b8688900b409c4a22a673ccd09f71 Mon Sep 17 00:00:00 2001 From: Daniel Olsen Date: Wed, 1 Jul 2020 22:18:36 +0200 Subject: [PATCH] add target vmaf to client Former-commit-id: ecf32d4045e90a524917eaad202ddb6f249f7d28 --- .gitignore | 1 + src/main.rs | 1 - src/static/client.sh | 108 ++++++++++++++++++++++++++++++++++++++++++- src/workunit.rs | 35 ++++++++++++-- 4 files changed, 139 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index ea8c4bf..ae4d0ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/result \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index fbef9ef..eb4836f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -111,7 +111,6 @@ fn get_job(id: Uuid, shared: State) -> Result, NotFound pub struct RealIP(std::net::IpAddr); - impl<'a, 'r> rocket::request::FromRequest<'a, 'r> for RealIP { type Error = (); fn from_request(request: &'a rocket::Request<'r>) -> rocket::request::Outcome { diff --git a/src/static/client.sh b/src/static/client.sh index 506105a..939c5d2 100755 --- a/src/static/client.sh +++ b/src/static/client.sh @@ -171,8 +171,8 @@ while true; do rm "$input" fi ;; - "FFMPEG") - echo "Starting FFMPEG encode" + "FFMPEGQ") + echo "Starting FFMPEG Q encode" two_pass=`echo $options | jq -r .two_pass` @@ -233,6 +233,110 @@ while true; do continue fi ;; + "FFMPEGVMAF") + echo "Starting FFMPEG VMAF encode" + + two_pass=`echo $options | jq -r .two_pass` + + if [[ $two_pass = true ]]; then + echo "Running in two-pass mode" + + pix_fmt=`echo $options | jq -r .pix_fmt` + + b_v=`echo $options | jq -r .b_v` + + tiles=`echo $options | jq -r .tiles` + lag_in_frames=`echo $options | jq -r .lag_in_frames` + + gop=`echo $options | jq -r .gop` + if [[ $gop != "null" ]]; then + flag_g="-g $gop" + else + flag_g="" + fi + + speed=`echo $options | jq -r .speed` + + vmaf_target = `echo $options | jq -r .vmaf` + q_min=`echo $options | jq -r .q_min` + q_max=`echo $options | jq -r .q_max` + q="foo" + last_q="bar" + best="$q_min" + echo "Finding VMAF!" + while true; do + echo "$q_min $q_max" + q=`echo "($q_min + $q_max)/2" | bc` + if [[ $q == $last_q ]]; then + echo "highest q over target is:" + echo $best; + fi; + last_q="$q" + + echo "trying q: $q" + + ffmpeg -threads 1 -y -i "$input" -c:v libaom-av1 -strict experimental -an \ + -vf scale=$width':'$height -pix_fmt $pix_fmt \ + -crf $q -b:v $b_v \ + -tiles $tiles -lag-in-frames $lag_in_frames \ + -cpu-used 5 -f ivf $input.out.ivf >/dev/null + ffmpeg -threads 1 -r 24 -i $input.out.ivf -r 24 -i $input -filter_complex "[0:v][1:v]libvmaf=log_fmt=json:log_path=$input.vmaf" -f null - >/dev/null + + vmaf=`cat $input.vmaf | jq -r '."VMAF score"'` + echo "current VMAF = $vmaf" + + result=`echo "$vmaf >= $target_vmaf" | bc` + + if [[ $result -eq "1" ]]; then + echo "Found value over target! $q = $vmaf" >&2 + crf_min=`echo $q - 1 | bc` + if [[ $q -gt $best ]]; then + echo "Found better value! $q" >&2 + best=$q + fi + elif [[ $result -eq "0" ]]; then + crf_max=`echo $q + 1 | bc` + fi + done; + rm $input.out.ivf + rm $input.vmaf + + set +e + ffmpeg -y -i $input -c:v libaom-av1 -strict experimental -pass 1 -an \ + -vf scale=$width:$height -pix_fmt $pix_fmt \ + -crf $best -b:v $b_v \ + -tiles $tiles -lag-in-frames $lag_in_frames $flag_g \ + -cpu-used $speed -f ivf /dev/null + retval=$? + if [ $retval -ne 0 ]; then + echo "Error running encode pass 1" + curl -s -L "$base_url"/edit_status/"$job_id"/error || true + echo "" + continue + fi + + ffmpeg -y -i $input -c:v libaom-av1 -strict experimental -pass 2 -an \ + -vf scale=$width:$height -pix_fmt $pix_fmt \ + -crf $best -b:v $b_v \ + -tiles $tiles -lag-in-frames $lag_in_frames $flag_g \ + -cpu-used $speed -f ivf $input.out.ivf + retval=$? + if [ $retval -ne 0 ]; then + echo "Error running encode pass 2" + curl -s -L "$base_url"/edit_status/"$job_id"/error || true + echo "" + continue + fi + + + set -e + + echo "Deleting Source and Temporary files" + rm "$input" "ffmpeg2pass-0.log" + else + echo "one-pass mode is not supported!" + continue + fi esac set +e diff --git a/src/workunit.rs b/src/workunit.rs index c45cc5b..00d6c1e 100644 --- a/src/workunit.rs +++ b/src/workunit.rs @@ -52,7 +52,8 @@ impl WDesc { #[derive(Debug, Serialize, Deserialize, Clone)] pub enum EOptions { AOMENC(AomencO), - FFMPEG(FffmpegO) + FFMPEGQ(FffmpegOQ), + FFMPEGVMAF(FffmpegOVMAF) } impl Default for EOptions { fn default() -> Self { @@ -82,7 +83,7 @@ impl Default for AomencO { } #[derive(Debug, Serialize, Deserialize, Clone)] -pub struct FffmpegO { +pub struct FffmpegOQ { pub two_pass: bool, pub crf: u8, pub b_v: String, @@ -92,7 +93,35 @@ pub struct FffmpegO { pub tiles: String, pub speed: u8 } -impl Default for FffmpegO { +impl Default for FffmpegOQ { + fn default() -> Self { + FffmpegO { + two_pass: true, + crf: 30, + b_v: "0".to_string(), + lag_in_frames: 35, + gop: Option::None, + pix_fmt: "yuv420p10le".to_string(), + tiles: "1x1".to_string(), + speed: 4 + } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct FffmpegOVMAF { + pub two_pass: bool, + pub vmaf: u8, + pub crf_min: u8, + pub crf_max: u8, + pub b_v: String, + pub lag_in_frames: u8, + pub gop: Option, + pub pix_fmt: String, + pub tiles: String, + pub speed: u8 +} +impl Default for FffmpegOVMAF { fn default() -> Self { FffmpegO { two_pass: true,