Author Topic: Tutorial For For Screenshots with MPV on Linux  (Read 1307 times)

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #20 on: January 11, 2017, 08:06:34 pm »
That's only one issue. It has a second more pressing issue. The interval between shots grows as the script runs. Let say the interval is 200. The distance between the fist 2 will be about 200. But the next interval will be 260. The next 300. Then it'll jump to 500 or 600. And so on till it jumps past the video s total length. The IPC will still run, but video will end with after around 10 or 15 screenshots. I put loop-file=INF as a stopgap till I solve it.
BTC 1FhCLQK2ZXtCUQDtG98p6fVH7S6mxAsEey
We did not invent the algorithm. The algorithm consistently finds Jesus. The algorithm killed Jeeves.
The algorithm is banned in China. The algorithm is from Jersey. The algorithm constantly finds Jesus.
This is not the algorithm. This is close.

Offline der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #21 on: January 12, 2017, 03:23:29 am »
i didn't look at the script too closely and just assume what the script does by the variable names.
$currentFrame - the current position in the video stream, the absolute position you want to seek to (frame number)
$currentTime - the current position in the video stream, the absolute position you want to seek to (timestamp secs)
$intervalFrame - seek interval (frame number)

lets say this is kinda the problem i meant. here a list of problems or i think are a problems.
  • second line below, you add a frame count to a timestamp in seconds, should be same unit. since frame numbers are fps-times bigger than the timestamp in seconds this will add very fast.
  • first line below, you seek by frame count. this only works with a time
  • first line below, you use a relative seek. meaning it will seek from the current position, that is the position you previously sought to. this wouldn't be much of a problem if you would seek by the interval (if we would ignore the start frame). since you seek by an absolute position (second line below, you add an interval to the old position and calculate the new position where you want to be) the seeks add up with every loop iteration (so you add the interval twice per iteration). this is either fixed by using an absolute seek or using just the interval to seek.

Code: [Select]
echo '{ "command": ["seek", '$currentFrame'] }' | socat - /tmp/mpvsocket
...
currentFrame="$(bc -l <<< "$currentTime + $intervalFrame")"

illustrating the add up problem from the relative seek, assuming the units were the same, not adding up frames to a time. assuming intervalFrame = 10.

iteration 1: currentFrame 0, current pos video 0
iteration 2: currentFrame 10, current pos video 10
iteration 3: currentFrame 20, current pos video 30
iteration 4: currentFrame 30, current pos video 60

this should fix it, assuming my assumptions were right.
Code: [Select]
echo '{ "command": ["seek", '$currentTime'] , "absolute"}' | socat - /tmp/mpvsocket
...
currentFrame="$(bc -l <<< "$currentFrame + $intervalFrame")"
« Last Edit: January 12, 2017, 03:30:19 am by der richter »

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #22 on: January 12, 2017, 06:14:51 am »
okay Changing

Code: [Select]
echo '{ "command": ["seek", '$currentFrame'] }' | socat - /tmp/mpvsocket

to

Code: [Select]
echo '{ "command": ["seek", '$currentFrame', "absolute"] }' | socat - /tmp/mpvsocket

Fixed it. Some Time-stamps are rounded down on, but the math holds consistent so i deem it acceptable. In my test video the time-stamps  with these settings:

frame -f "vidfile" -s 200 -n 20 -i 300

are: 200, 499, 800, 1100 1400, 1700, 1999, 2300, 2600....

So even though Some are rounded down one it seems it fixed it.

I didn't change the variable because i already tried that and it would only output the same frame on a loop. I also added a second to the sleep pause between the seek IPC call and the Screenshot IPC call as the Screenshot IPC call would still sometime override the Seek one. It would create duplicate screenshots with two different time-stamps.

Edit: trying with the changed seek call still did the same thing.

Edit two: I read it wrong and retried it. instead it would only add one frame not the interval.

Edit 3: It fixed the -i switch, but the -f -s -n set up is broken now it functions the same as the -i switch, but it used fixed timestamps bases on some wonky math. think 'ill strip it out  and simply direct those who want a simpler set up to the first script and only use this one for predetermined set intervals.

Edit4: seems it has something to do with how the seek reletive and seek absolute functions owrk different. The origon script took advantage of the seek relative function to move to the next invterval. I've solved it ( and the issie mentioned in edit3) by adding what i call the flipBit. It's an extra variable to fix the math so that it seeks over most of the video.

Edit 5: A TYPO. A typo of all things! That's what was breaking it. I'm going to retest some things...
« Last Edit: January 12, 2017, 09:08:57 am by Wisperer »
BTC 1FhCLQK2ZXtCUQDtG98p6fVH7S6mxAsEey
We did not invent the algorithm. The algorithm consistently finds Jesus. The algorithm killed Jeeves.
The algorithm is banned in China. The algorithm is from Jersey. The algorithm constantly finds Jesus.
This is not the algorithm. This is close.

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #23 on: January 12, 2017, 10:34:12 am »
Tada! The Final Functional code! Hours of testing! Made sure it all works! BTW renamed flipBit to fixBit as it no longer flips anything. but still fixes maths.

Code: [Select]
#!/usr/bin/env bash

while getopts ":f:s:i:n:v" opt; do
  case $opt in
    f)
      declare -r file="$OPTARG"
      ;;
    s)
      declare -r startFrame="$OPTARG"
      ;;
    i)
      declare -r intervalScreenshots="$OPTARG"
      ;;
    n)
      declare -r numberScreenshots="$OPTARG"
      ;;
    v)
      declare -r verbose="TRUE"
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

# Quit if we missed -f, -s or -n
if [[ -z "$file" ]] || [[ -z "$startFrame" ]] || [[ -z "$numberScreenshots" ]] ; then
  printf 'You must at the minimum set -f, -s and -n
-f <the video file>
-s <the number of the frame of the first screenshot>
-i <the interval of frames of the next screenshot>
-n <the number of screenshots you want>
-v <TRUE or FALSE>\n'
  exit 1
fi
 #start mpv
 
 mpv --pause --quiet --no-audio --osd-level=0  --no-border --vo=opengl --scaler-lut-size=8 --scale=spline36 --cscale=spline36 --opengl-fbo-format=rgb16 --linear-scaling --geometry=x1080 --screenshot-template=%F_%ws --input-ipc-server=/tmp/mpvsocket "$file"  > /dev/null 2>&1 &
 
 
# Informations grabbing
#declare -r filename="$(basename "${file}")"
#declare -r lastFrame="$(mpv --term-playing-msg='frame=${estimated-frame-count}' --load-scripts=no --quiet --vo=null --ao=null --no-sub --no-cache --no-config --frames 1 "$file" | grep 'frame' | cut -d '=' -f2)"
#declare -r fpsVideo="$(mpv --term-playing-msg='fps=${estimated-vf-fps}' --load-scripts=no --quiet --vo null --ao=null --no-sub --no-cache --no-config --frames 1 "$file" | grep 'fps' | cut -d '=' -f2)"

sleep 1

 declare lastFrame=$(echo '{ "command": ["get_property", "estimated-frame-count"]}' | socat - /tmp/mpvsocket | cut -d":" -f2 | cut -d , -f1)

sleep 1

declare fpsVideo=$(echo '{ "command": ["get_property", "estimated-vf-fps"]}' | socat - /tmp/mpvsocket | cut -d":" -f2 | cut -d , -f1)



sleep 1

# Set fixBit
#Needed to correct math. Otherwise the seek interval will be too large. This will cause seeking to hit the file end before numberScreenshots is achieved..
#Change if deemed needed. It will increase/decrease the interval when using only the -s and -n switches. Larger values will result in smaller intervals. Smaller values will result in larger intervals.Using -i will bypass this.

 declare -r fixBit=25
# Declare interval for each screenshot
if [[ -z "$intervalScreenshots" ]] ; then
  declare -r diffFrame="$(bc -l <<< "$lastFrame - $startFrame")"
  declare -r preFrame="$(bc -l <<< "$diffFrame / $numberScreenshots")"
  declare -r intervalFrame="$(bc -l <<< "$preFrame / $fixBit ")"
else
  declare -r intervalFrame="$intervalScreenshots"
fi

# Looping to take screenshots
declare currentFrame="$startFrame"
for i in $(seq 1 "$numberScreenshots") ; do
 
   declare currentTime="$(bc -l <<< "$currentFrame / $fpsVideo")"
 
  if [[ -n "$verbose" ]] ; then
    printf 'Filename: %s\n\n' "$filename"
 
    printf 'Current time: %.2f\n\n' "$currentTime"
   
    printf 'Last frame: %s\n' "$lastFrame"
    printf 'FPS: %s\n' "$fpsVideo"
    printf 'Interval: %s\n' "$intervalFrame"
    printf 'Screenshot: %02d\n\n\n' "$i"
 
 fi
  # Debug line
  # mpv --really-quiet --load-scripts=no --no-audio --no-sub --frames 1 --start "$currentTime" "$file" -o "${filename%.*}_${currentTime%%0*}.png"

   
   
   
   
   echo '{ "command": ["set_property", "pause", true] }' | socat - /tmp/mpvsocket
   
   sleep 2
   
   echo '{ "command": ["seek", '$currentFrame', "absolute" ] }' | socat - /tmp/mpvsocket
   
   sleep 2
   
   echo '{ "command": ["screenshot", "window"] }' | socat - /tmp/mpvsocket
   
   sleep 2
   
   

currentFrame="$(bc -l <<< "$currentFrame+$intervalFrame")"



done
« Last Edit: January 12, 2017, 11:01:30 am by Wisperer »
BTC 1FhCLQK2ZXtCUQDtG98p6fVH7S6mxAsEey
We did not invent the algorithm. The algorithm consistently finds Jesus. The algorithm killed Jeeves.
The algorithm is banned in China. The algorithm is from Jersey. The algorithm constantly finds Jesus.
This is not the algorithm. This is close.

Offline der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #24 on: January 12, 2017, 03:27:19 pm »
i think you still have an issue with mixing units.

correct me if i am wrong.
you still seek by a frame number (+ a pseudo timestamp, see next senctence), but seeking only works for timestamps.
the so called fixBit you introduced shouldn't be needed. you divide a frame interval by 25, which gets you a time stamp of a video with 25fps. most videos are ~24fps and since you divide the interval by 25 it's obvious it fixes your issue of seeking too much.

i think just removing the fixBit and changing following line
Quote
echo '{ "command": ["seek", '$currentFrame', "absolute"] }' | socat - /tmp/mpvsocket
to
Code: [Select]
echo '{ "command": ["seek", '$currentTime'], "absolute"] }'  | socat - /tmp/mpvsocket
should do the trick.

currently it somewhat works, but not completely as intended, since $currentFrame is set to a low value since it starts at $startFrame and you convert $intervalFrame to a pseudo timestamp of a 25fps video with your fixBit.

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #25 on: January 12, 2017, 07:46:13 pm »
IV already tried that. It doesn't NOT work. It loops the startFrame. I had already tried it before you said it. I tried it after you said it. I tried it free I fixed that typoed variable. Same thing all three times. It would just loop that first frame and wouldn't seek forward. I've already said that too I think. Maybe not as clearly as needed though. Well it did seek forward by one timestamp per loop when I combined it with the variable change you suggested.

And the fix bit is I math magical corrector. Otherwise the interval tis was too large. I tried 10 and it did not work. 20 was close. 30 was too high. So I compromise at 25 and it got it to seek AL the way totheend.
Maybe I can see it to =estimated_fps?
As a side not I tested it on 4  other files. On had a variable frame rate that averaged out to be 29 fps. I even used media info to check. And it would seek past the file end even when the others worked.


Maybe it I set fix it to fps it might work.
« Last Edit: January 12, 2017, 08:13:01 pm by Wisperer »
BTC 1FhCLQK2ZXtCUQDtG98p6fVH7S6mxAsEey
We did not invent the algorithm. The algorithm consistently finds Jesus. The algorithm killed Jeeves.
The algorithm is banned in China. The algorithm is from Jersey. The algorithm constantly finds Jesus.
This is not the algorithm. This is close.

Offline der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #26 on: January 13, 2017, 03:05:39 am »
chill out geez. there is no need to overreact like this.

i told you what the problem with your magical "fixBit" is. obviously using the estimated fps would somewhat fix it. though like the name suggests, it's only estimated and not the real fps. it will totally break with VFR vide, on broken timestamps and maybe other circumstances. mpv is not fit to do something frame based, since it doesn't really know what "frames" are. you would need to index the file somehow beforehand to get a proper frame based seeking, though that's not possible with mpv. vapoursynth would be a better alternative, but that is somewhat out of scope.

don't expect any more from me. even though i could help more or even fix your problems, i now don't feel like helping you any more than i already did.

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #27 on: January 13, 2017, 05:42:38 am »
Alas. Well c'est la vie.

Your help was welcome. I will continue to work on it anyhow. Didn't mean to run you off. I was just trying g to point out I already tried it. Not once but three times.

I will ensure you get proper thanks and a note about your massive help on this. Cheers.
« Last Edit: January 13, 2017, 07:31:07 am by Wisperer »
BTC 1FhCLQK2ZXtCUQDtG98p6fVH7S6mxAsEey
We did not invent the algorithm. The algorithm consistently finds Jesus. The algorithm killed Jeeves.
The algorithm is banned in China. The algorithm is from Jersey. The algorithm constantly finds Jesus.
This is not the algorithm. This is close.