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

Offline Wisperer

  • Member
  • Posts: 82
Tutorial For For Screenshots with MPV on Linux
« on: January 04, 2017, 08:28:25 am »
For awhile now I've been trying to find an acceptable way to take screenshots on Linux. I've tried various methods with different degrees of success. I finally have a Bash script that will allow you to take screenshots in linux using only Mpv to render the images.

Disclaimer: You must be running Linux.
Optional install optionse are available at https://mpv.io/installation/


Tested Linux Disros:

Ubuntu 15.10
Ubuntu 16.04 LTS
Ubuntu 16.10
Arch Linux (Using bash, not zsh)



Requirements:

Open Terminal Window
Ctrl+ALT+T will do it

A Note: Remember Linux is case sensitive

Install MPV

You first need to install MPV. On Ubuntu this is achieved via the Apt-Get command.. However the Distro packages are too far out of date. You need the current stable MPV. To do this you need to install the offical PPA at https://launchpad.net/~mc3man/+archive/ubuntu/mpv-tests


First Run
sudo add-apt-repository ppa:mc3man/mpv-tests
This adds the PPA to the system.

Then Run
sudo apt-get update
This updates the system to let it know there are new packages to use.

Finally Run
sudo apt-get install mpv
This installs MPV

Install socat

Socat is a program that allows MPV to be controlled via echoed IPC JSON calls from terminal.

Run
sudo apt-get install socat

For Arch:

The Arch repos are more up to date then the Ubuntu repos. As such:

Run First:
sudo pacman -S mpv

Then Run:
sudo pacman -S socat

Everything else should be the same.


The Bash Script



For those not in the know a Bash script is a file similar to a Windows .bat file. It allows you to run a series of commands by executing a single file with a single line of code. Now I have two scripts available. Both can serve the same function. The first is simpler, but the second one is far more flexible once you get the hang of it.

Script One: Simple, But Limited

This one is simple. you simply add a filename and the desired number of screen shots. It then divides the total length (in second) of the video by the number of screen shots desired. It then uses that to seek out where to take them. It's semi-random and its downside is that if you have two releases of slightly different lengths it's impossible to use it reliably for comparisons. However for releases of the same length it's a simple life saver.

First Copy The Code
Code:
Sorry but you are not allowed to view spoiler contents.

This script is simple to use. It takes a screenshot and then ouputs it into the directory it was taken.

Next Create A File
Name It "mpv-shot.sh"
This is important. You can name it whatever, however this is how I'll refer to it from here on out. However please make sure it ends in .sh. If you choose your own name remember to substitute your name wherever you see "mpv-shot.sh" .

Then Paste The Code
You put it into mpv-shot.sh. Simply copying the code and pasting it will do. Then save it naturally.

IMPORTANT: Mark The File As Executable.
Simply right click the file and locate Properties. Then look for Permissions. Under Permissions you should see an un-selected tickbox to make it executable. Select it. Then exit Properties.

Using mpv-shot.sh

First Move mpv-shot.sh
Put mpv-shot.sh into the desired folder. It's simplest to run it from the same location as the file you wish to run it on, but it isn't needed.

If In The Same Location
Hit CTRL+ALT+T tp open terminal.

Then Use cd To Move To The Folder.
cd path/to/your/folder

Run Script
./mpv-shot "videofile.ext" #of screenshots
This will then create the desired number of screenshots.

If Not In Same Location
cd to the location of mpv-shot.sh as above.
Use ./mpv-shot.sh "path/to/vidoefile.ext" <#of screenshots>

Simple to use.



Bash Script Two: Flexibility

This script differs in two very big ways. One is it uses frames rather then time in seconds. Second it has several options for intervals and start time. The basic set up is the same as the first. The main difference will be in usage.

Copy The Code
Code:
Sorry but you are not allowed to view spoiler contents.


Then Create A File
The file will be called mpv-frame.sh to ensure that there is no confusion between the two files. As with before you may use your own name.

Paste Code
Put the code into mpv-frame.sh. Simple Copy/Paste will do.

IMPORTANT: Mark The File As Executable.
Simply right click the file and locate Properties. Then look for Permissions. Under Permissions you should see an un-selected tickbox to make it executable. Select it. Then exit Properties.

Using mpv-frame.sh
Usage is a bit more complex. The directory moving from mpv-shot.sh still applies. It also outputs the screenshots in the working directory. It also has several options however.

Options

-f | Video File | File You Want To Use
-s | First Frame to be Read | Start Position
-i | Interval to Next Shot | Preset The Interval
-n | Number of Screenshots | Self Explanitory
-g | Aspect Ratio | 1080p Or 720p Other
-v | Verbose (More output in console) | Use -v true

-f, -s, -n are mandatory

Default Usage
./mpv-frame.sh -f "Videofile.ext" -s (Start Point) -n  (# Of Screenshots)
This functions similar to mpv-shot.sh. It will simply take a number of shots from the starting frame to the end of the video at intervals set by the number of screen shots.

Advance Usage Of mpv-fram.sh

You can toggle the switched in various ways.

Examples:

To Take a Set Number of Screens From Start At Intervals
./mpv-frame.sh -f "Videofile.ext" -s 200 -i 50 -n 10
This will take 10 screen shots. One every 50 frames starting at frame 200.

Matching Two Releases

Lets say you have two releases. File one is 5 second longer then the other because group two cut 5 seconds from the end of file two. 5 seconds isn't much, but at 24 fps it adds up to 120 extra frames. Files with larger differences will have larger frame differences. Different encoding settings may affect this as well.With mpv-shot.sh nothing could save you. With mpv-frame.sh however you can adjust the options to match up frames.

First Pass

Release One: ./mpv-frame.sh -f "Videofile1" -s 200 -n 20
Release Two: ./mpv-frame.sh -f "Videofile2"-s 200  -n 20
Since release two is shorter this leaves the screenshots a few frames off. There isn't anything you can do with just these three options.

Second Pass

Release One: ./mpv-frame.sh -f "Videofile1" -s 200 -i 200 -n 20
Release Two: ./mpv-frame.sh -f "Videofile2"-s 200 -i 200 -n 20
Here we added the -i switch. We set it to 200. The first took a screenshot from frame 200 to the videos end at every 1/20th of the video. With this switch set to 200 it instead takes a Screenshot every 200th frame starting at 200. It then stops once it hits 20 screenshots. It should match perfectly.

Third Pass

However lets say video two is also off because a bit is cut from the beginning as well. That means frame 200 in video one wont match frame 200 in video two. Lets say its only one frame shy at the start.

Release One: ./mpv-frame.sh -f "Videofile1" -s 200 -i 200 -n 20
Release Two: ./mpv-frame.sh -f "Videofile2"-s 201 -i 200 -n 20
By making -s on video two 201 we bump its start position up one to line it up with video one. Dropping video one to 199 would work as well. The screenshots should now match in either case.

Fourth Pass

Lets say instead one is 1080p and two is 720p. And you have a third release that's also 1080p. You can use the optional -g switch to scale them as needed.


Release One: ./mpv-frame.sh -f "Videofile1" -s 200 -i 200 -n 20
Release Two: ./mpv-frame.sh -f "Videofile2"-s 200 -i 200 -n 20 -g x1080
Release Three: ./mpv-frame.sh -f "Videofile3" -s 200 -i 200 -n 20

By setting -g x1080 on Videofile3 we were able to use MPV internal scaler to scale the 720p file up to 1080p. If you wanted to you could also set Videofile1 and Videofile3 to -g x720 and scale them down. Either way it works.


The original code was found here: https://github.com/Kcchouette/MPV-screenshots

It was in turn based on code that had been posted here http://askubuntu.com/questions/684834/need-help-with-mpv-bash-script/685735#685735

A special thanks to der richter who put up with me long enough to actually get this code functional. His suggestions and help were massive. Thanks dude.

And a thanks to TomG. He suggested I use cut instead of grep. He can be found on the #linuxmint-chat IRC channel on Spotchat.

ChangeLog
Sorry but you are not allowed to view spoiler contents.
« Last Edit: February 26, 2017, 06:21:37 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.

Online der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux
« Reply #1 on: January 04, 2017, 12:18:54 pm »
you probably put quite a lot of work into that but this method won't get you acceptable screenshots, especially not in any way that suits bakabt.

using  --vo image with mpv won't get you any of the advanced scaling and conversions the opengl vo (with 'screenshot window') gives us. which would give us a somewhat comparable result to other recommended methods for taking screenshots for comparisons. even just for screenshots on descriptions this won't give us a faithful representation of the release.

this is a bit of a guess, i believe the image vo just uses ffmpeg's swscale to do colour conversion and chroma scaling. which is rather suboptimal. the chroma scaling is horrendous and gives us sever chroma aliasing and if i would guess it even gets the chroma placing wrong. since screenshots tell more than words:

vo opengl spline36 | vo image

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux
« Reply #2 on: January 05, 2017, 06:09:52 am »
It may because of my screen resolution, but I could barely tell the difference between those two images. Even then the differences were minimal. A very slight difference in color saturation and line sharpness. Even so Looking at the wiki is does specify -vo opengl-hq. I'll look into adapting the script, but I'm not entirely sure at how feasible that is. The entire loop is built around -vo image.

Edit: seems changing vo image to vo opengl-hq in my test script didn't break anything major. In fact it may have solved an issue I was having with optional directory placement

Edit 2: More testing has reviled no issues. seems as long as i keep the -frames 1 switch it will only render a single frame and output it as as screenshot no matter what other rendering options i use. Changed it in my Tutorial.
« Last Edit: January 05, 2017, 07:43:06 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.

Online der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux
« Reply #3 on: January 05, 2017, 02:40:17 pm »
the difference are not minimal at all, there is sever chroma aliasing. screenshots taken like that are completely useless to bakabt.

no you can't just change to opengl-hq from the image vo. first opengl-hq enables debanding which leads to a not exact representation of the source (if you use a newer mpv it's also --vo=opengl --profile=opengl-hq). second your script should use mpv correctly in the first place. you need to decide if you either want to use the encoding mode or the image vo. when using the image vo use the corresponding options (--vo-image-format=<format> --vo-image-outdir=<dirname>) for it and not the output option --o for the encoding mode. that way it will use the high quality resampling of swscale and you won't get sever chroma aliasing and a better color conversion. though this is still not on the level of a properly setup opengl output or similar high quality methods. for one swscale uses lanczos for resizing and you will get a bit of chroma ringing, though those screenshots should be okay to use for descriptions not so much for comparisons.

if you want to use the encoding mode of mpv to output images you need to properly set it up. i myself never used it so i can't really help you properly with it. for a start opengl should be set up with at least the following (note i am not using opengl-hq because of the debanding though you could use opengl-hq and set deband=no)

Code: [Select]
vo=opengl
opengl-fbo-format=rgb16
scaler-lut-size=8
scale=spline36
cscale=spline36

additionally you need to feed it either RGB or 4:4:4 fullchroma (and convert it with swscale to RGB) to write a png image. i don't know how this is done properly but you probably need to set --ofopts, --ovcopts and maybe a videofilter --vf.

another method would be using mpv as normal and use input commands via the IPC to make screenshots, that way you get a proper representation of the source material.

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux
« Reply #4 on: January 06, 2017, 06:59:15 am »
I'll get to work then. I actually posted this here in part because i did need a bit of feedback on how to tweak this in. I know how to use the various switches, i just wasn't sure what to set. You help is most appreciated.

Edit:

From what i can tell i can do 90% of what the AvsPmod/Dither combo does entirely with opengl option switches and a few tweaks with a vf filter chain.

And I'd say the script functions closer to the ExRelease script then the AvsPmod/Dither combo. So once i get my render setting correct I'd say in done.

and using IPC is WAY over my head.

Edit 2:

After doing a lot lot of reading up on how dither tools and AVIsynth work i think I've managed to reproduce MOST of the  AvsPmod/Dither script with this string

mpv --really-quiet --ao=null --frames 1 --start "$currentTime" "$file" --vo=opengl --scaler-lut-size=8 --scale=spline36 --cscale=spline36 --opengl-fbo-format=rgb16 --linear-scaling  --vf=scale=1920:1080 -o "$(printf '%02d_%s.png' "$i" "${filename%.*}")"
  currentFrame="$(bc -l <<< "$currentFrame + $intervalFrame")"
« Last Edit: January 06, 2017, 11:09:41 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.

Online der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux
« Reply #5 on: January 06, 2017, 11:37:30 am »
this still has the chroma problem. you might want to ask on the irc mpv channel about it.

[edit]
tbh i am not even sure if the encoding mode is even influenced by the vo, if not your only real solution would be using input commands.
« Last Edit: January 07, 2017, 11:35:41 am by der richter »

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux
« Reply #6 on: January 06, 2017, 12:37:35 pm »
this still has the chroma problem. you might want to ask on the irc mpv channel about it.+

[edit]
tbh i am not even sure if the encoding mode is even influenced by the vo, if not your only real solution would be using input commands.

I haven't even used any encoding options. The -o switch is only used to create a usable filename for the output. Everything is either opengl settings or video filters used for play back. Plus while there are options for chroma in mpc actual chroma scaling beyond --cscale=spline36 is limited and is only found in the -formate=fmt= Filter sub-options. I could add some dithering within the opengl setting, but i think that all i can do with only mpv. There are some user shaders, but I'm just now looking into tyhose.
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.

Online der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #7 on: January 07, 2017, 12:27:26 am »
if you use the --o option mpv operates in encoding mode, regardless of using any encoding options. at the moment the output doesn't even look close to what opengl would look like.

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #8 on: January 07, 2017, 11:09:07 am »
Tell you what. give a video to use for testing and a few reference images then, be cause i guess to don't know what opengl is suppose to look like even though my system uses it natively for literally everything.
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.

Online der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #9 on: January 08, 2017, 01:24:57 pm »
Quote
..., be cause i guess to don't know what opengl is suppose to look like even though my system uses it natively for literally everything.
this doesn't make any sense at all. the opengl vo of mpv just uses opengl to display the content. the way it is processed and displayed is not related to opengl and to "literally everything" else on your system and how it looks like.

any video should do. the chroma aliasing is usually well visible on all red/darkish edges like on the example screen given. if you really can't see the chroma aliasing on the screen i provided then you are one of the 'fortunate' who can be ignorant about it.

if you really need example screens you can make them yourself. take a screenshot the usual way, just with the input command "screenshot window", and compare that to your output. though since you can't see the problem in my screens it might be hard for you to properly compare them.

using the IPC (input commands) is really easy. here a basic example. start mpv like that, additional to your options sans the --o.
Code: [Select]
mpv --input-ipc-server=/tmp/mpvsocket FILE

mpv can now be controlled like this.
Code: [Select]
#seek to 15 mins, 30.5 secs
echo '{ "command": ["seek", "15:30.5", "absolute"] }' | socat - /tmp/mpvsocket

#make a screenshot
echo '{ "command": ["screenshot", "window"] }' | socat - /tmp/mpvsocket

#quit mpv
echo '{ "command": ["quit"] }' | socat - /tmp/mpvsocket

though with this method it will open an actual window. another problem with this method could be that the window is restricted in size by your wm and since screenshots are taken from the window they might be downscaled. if windows can go beyond screen bounds it will be fine.

if you need all screens scaled to the same size you can use --geometry=x1080 option. with this example all screens will be scaled (by the opengl vo scalers) to a height of 1080 pixel and it keeps the aspect ratio. it's probably also advisable to use --no-osc, --osd-level=0 and --no-border with this method.

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #10 on: January 09, 2017, 06:21:14 am »
I've already tried comparing my script images with MPV images made from the launching the player. I used the same Opengl  and -vf settings and i literally compared a set of 20 images for over 2 hours and couldn't tell them apart.

Hmm... Still can't see the difference offhand this way, but I do like this way of controlling the player.

Edit:

I went to upload my pics to show you what im telking about, but Imgur seems to want to corrupt the images...

from mpv using ipc http://imgur.com/a/MmstQ

From script...

http://imgur.com/a/HKKBD

Edit2: Updating to the mpv git master seems to have broke something really horably...
Or it seems Something in general is wrong.... Crap... I think there is something fundamentally wrong here now that wasn't highlighted till i update MPV again. The Last MPV update royally screwed it up Subtitle rendering from the script, but it seems to work normally in the player.
           
« Last Edit: January 09, 2017, 09:58:34 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.

Online der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #11 on: January 09, 2017, 12:55:59 pm »
if you use the IPC method there shouldn't be a need for any video filter (--vf). the uploaded screens are jpgs, so no use looking at them.

what exactly is broken?

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #12 on: January 09, 2017, 08:09:11 pm »
No they're PNG files. I have mpv set to output PNG files globally. And if I try to put a PNG extension on a JPEG file my file viewer will throw a fit and my image viewer will refuse to render the image. I use Thunar for reference. I use xfce as my desktop environment in case it's relevant.

Yeah I'm thinking of rewriting my script into a file launcher and writing a seek script that will pause the video are you tell it to and use the IPC to take the screenshot. Two reason. One I'll never remember those vo options. Two I doubt anyone other then the most die-hard Linux user will want to mess with the IPC directly.

And all the subtitles are rendered black and smeared.
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.

Online der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #13 on: January 10, 2017, 02:13:20 am »
no the uploaded files are JPEGs. they are also subsampled.
Code: [Select]
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Mime type: image/jpeg
  Class: DirectClass
  Geometry: 1920x1080+0+0
  Resolution: 72x72
  Print size: 26.6667x15
  Units: PixelsPerInch
  Type: TrueColor
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit
  Channel statistics:
    Pixels: 2073600
    Red:
      min: 0 (0)
      max: 255 (1)
      mean: 121.729 (0.477367)
      standard deviation: 72.9651 (0.286138)
      kurtosis: -0.898138
      skewness: 0.304323
      entropy: 0.954717
    Green:
      min: 0 (0)
      max: 255 (1)
      mean: 124.657 (0.488852)
      standard deviation: 62.815 (0.246333)
      kurtosis: -0.871453
      skewness: 0.266079
      entropy: 0.969452
    Blue:
      min: 0 (0)
      max: 255 (1)
      mean: 123.993 (0.486248)
      standard deviation: 72.9125 (0.285932)
      kurtosis: -0.967259
      skewness: 0.129813
      entropy: 0.96046
  Image statistics:
    Overall:
      min: 0 (0)
      max: 255 (1)
      mean: 123.46 (0.484155)
      standard deviation: 69.7277 (0.273442)
      kurtosis: -0.886121
      skewness: 0.225671
      entropy: 0.961543
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Background color: white
  Border color: srgb(223,223,223)
  Matte color: grey74
  Transparent color: black
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 1920x1080+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: JPEG
  Quality: 75
  Orientation: Undefined
  Properties:
    date:create: 2017-01-10T02:02:12+01:00
    date:modify: 2017-01-09T11:48:24+01:00
    jpeg:colorspace: 2
    jpeg:sampling-factor: 2x2,1x1,1x1
    signature: c9545ef8df40c638da5466307e395e5db1e8f00d4ebace957c32fc3a7a25dd34
  Artifacts:
    verbose: true
  Tainted: False
  Filesize: 356KB
  Number pixels: 2.074M
  Pixels per second: 41.47MB
  User time: 0.040u
  Elapsed time: 0:01.049
  Version: ImageMagick 6.9.6-4 Q16 x86_64 2016-11-10 http://www.imagemagick.org

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #14 on: January 10, 2017, 06:18:00 am »
Okay here's what happened. i uploaded a PNG, but imgur converted it into a Jpeg file. I even uploaded a different file from my test images. I checked it before i uploaded it, and then after I redownloaded the image from imgur and tested it again.

Origonal file: http://i.imgur.com/NKk2kMP.png

AFter imgur: http://i.imgur.com/afepTRJ.png

But as you can also Posting images created my screenshot tool dont get warped or converted, so I'm not sure Whats happening.

Did i bit of research seems imgur converts and images over a certain size to low quality JPEG. it scaled a 16bit 9Mb png to an 8bit 199Kb jpeg

Edit: My rewrite is going well. I was able to salvage most of the loop and variable code. Not gunna post it yet as I'm still bug testing it.
« Last Edit: January 10, 2017, 08:23:28 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 #15 on: January 10, 2017, 10:10:51 am »
Okay I was forced to break it into two scripts to get it to work. One to launch the video

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

### Global variables
declare -r file="$1"

### Error handling
if [ -z "${file}" ];
then
    echo "ERROR: No video file supplied. Please enter a video file as argument."
    exit 1;
fi

 mpv --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"
 
 
exit 0

And one to loop the IPC calls. I'm working on adapting the second frame based script. THis is the first simpler one. There are a few stray variables i need to clean up still.



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

### Global variables
declare -r file="$1"
declare -r filename="$(basename "$file")"

### Error handling
if [ -z "${file}" ];
then
    echo "ERROR: No video file supplied. Please enter a video file as argument."
    exit 1;
fi

if [ ! -z "$2" ];
then
  declare -ri NUM_OF_SCREENSHOTS="$2"
  echo "WARNING: Overwrite default number of screenshots to ${NUM_OF_SCREENSHOTS}."
  sleep 3s
else
  declare -ri NUM_OF_SCREENSHOTS='9'
fi

# Get the total length of the video in seconds.
declare -i total_length="$(mpv "$file" --quiet --vo null --ao null --frames 1 --term-playing-msg 'duration=${=duration}' | grep 'duration' | cut -d '=' -f2 | cut -d '.' -f1)"

# Remove 4 seconds from the video so that it doesn't take screenshot at the ends.
let total_length-='4'

# Add 1 to the div number, like that the image is not at the end of the video
# else, for 1 picture total_length/1 = total_length, so the end
# with that, it'll be total_length/2
declare -i DIV_NUMBER="${NUM_OF_SCREENSHOTS}"
let DIV_NUMBER+='1'

# time_slice: At which time interval should mpv take screenshots.
let time_slice="${total_length}/${DIV_NUMBER}"

# time_at: When should mplayer take screenshots.
time_at=${time_slice};

# Looping to take screenshots.
declare name="${filename%.*}_${time_slice}"
declare -i i
for i in $(seq 1 "$NUM_OF_SCREENSHOTS")
do


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

  # Increment to the next time slice.
  let time_at+="${time_slice}"
 
 
done

exit 0

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.

Online der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #16 on: January 10, 2017, 01:48:32 pm »
don't use echo '{ "command": ["screenshot","subtitles"] }' | socat - /tmp/mpvsocket, use "screenshot window" like i suggested. that way the geometry option works, you also get subtitles and it takes a screenshot of the actual opengl output.

you should be able to start mpv in background with appending a "> /dev/null 2>&1 &" to the command. first part should redirect all the mpv output and the last "&" starts it in background, example "mpv FILE > /dev/null 2>&1 &". that way you should be able to use everything in one script.

i see you still open a separate mpv instance to get the duration of the file. you can also use the already started mpv instance and the IPC to get the duration.
Code: [Select]
echo '{ "command": ["get_property", "duration"]}' | socat - /tmp/mpvsocket

on a sidenote if you don't plan to change that already. it would probably be nice if you could set the "--geometry" option when calling the script. sometimes you don't want to scale at all or to a configurable height. even better would be to get all the resolutions of all files and calculate the biggest common resolution to use.

Offline Wisperer

  • Member
  • Posts: 82
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #17 on: January 10, 2017, 08:24:33 pm »
I'm tinkering as I go to try and squeeze as much as. I can into it. So I wasn't planning it, but I'll what I can do. Just remember I'm still new to programming in general and I only know bash. I'm learning as I go on this.

Edit been having a devil of a time getting the ipc to output duration to grep.
« Last Edit: January 11, 2017, 05:04:37 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 #18 on: January 11, 2017, 06:09:57 am »
Okay I had to get a bit of help with it, but i eventually got it . I'm going to work on getting the other frame script functional now. Any additions to this will have to wait.

BTW all those sleep 1 pauses are needed to keep the IPC call from interfering with each other.

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

### Global variables
declare -r file="$1"

### Error handling
if [ -z "${file}" ];
then
    echo "ERROR: No video file supplied. Please enter a video file as argument."
    exit 1;
fi

if [ ! -z "$2" ];
then
  declare -ri NUM_OF_SCREENSHOTS="$2"
  echo "WARNING: Overwrite default number of screenshots to ${NUM_OF_SCREENSHOTS}."
  sleep 3s
else
  declare -ri NUM_OF_SCREENSHOTS='9'
fi
 #Start MPV
mpv --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 &
# Get the total length of the video in seconds.
 #declare -i total_length="$(mpv "$file" --quiet --vo null --ao null --frames 1 --term-playing-msg 'duration=${=duration}' | grep 'duration' | cut -d '=' -f2 | cut -d '.' -f1)"
 
 sleep 1

 total_length=$(echo '{ "command": ["get_property", "duration"]}' | socat - /tmp/mpvsocket |cut -d":" -f2 | cut -d . -f1)

# Remove 4 seconds from the video so that it doesn't take screenshot at the ends.
let total_length-='4'

# Add 1 to the div number, like that the image is not at the end of the video
# else, for 1 picture total_length/1 = total_length, so the end
# with that, it'll be total_length/2
declare -i DIV_NUMBER="${NUM_OF_SCREENSHOTS}"
let DIV_NUMBER+='1'

# time_slice: At which time interval should mpv take screenshots.
let time_slice="${total_length}/${DIV_NUMBER}"

# time_at: When should mplayer take screenshots.
time_at=${time_slice};

# Looping to take screenshots.
#declare name="${filename%.*}_${time_slice}"
declare -i i

 sleep 1
 
for i in $(seq 1 "$NUM_OF_SCREENSHOTS")
do


 echo '{ "command": ["set_property", "pause", true] }' | socat - /tmp/mpvsocket
 
 sleep 1
 
 echo '{ "command": ["seek", '$time_at', "absolute"] }' | socat - /tmp/mpvsocket
 
 sleep 1
 
 echo '{ "command": ["screenshot", "window"] }' | socat - /tmp/mpvsocket
 
 sleep 1
 
 
  # Increment to the next time slice.
  let time_at+="${time_slice}"
 
 
done

pkill mpv

exit 0

Edit: I got the Second one Mostly working. Seem the set interval switch is a bit broken.

Still something off with it, but it mostly works

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 --loop-file=inf --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
# Declare interval for each screenshot
if [[ -z "$intervalScreenshots" ]] ; then
  declare -r diffFrame="$(bc -l <<< "$lastFrame - $startFrame")"
  declare -r intervalFrame="$(bc -l <<< "$diffFrame / $numberScreenshots")"
else
  declare -r intervalFrame="$intervalScreenshots"
fi

# Looping to take screenshots
declare currentFrame="$startFrame"
for i in $(seq 1 "$numberScreenshots") ; do
 
   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"

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

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



done

« Last Edit: January 11, 2017, 11:04:12 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.

Online der richter

  • Former Staff
  • Member
  • Posts: 1235
  • Judgment
Re: Tutorial For For Screenshots with MPV on Linux{WIP}
« Reply #19 on: January 11, 2017, 02:00:01 pm »
if i would guess why your second script behaves not like expected on the interval seeks (if i understood the problem correctly), it's because you don't use an absolute seek even though you want one there. though i only skimmed through the script and read the var names.

if you really want a relative seek there, the problem is when using a relative seek instead of an absolute, that it uses a keyframe seek instead of an exact (hr/precise seek). so if you really want to use a relative seek use "relative+exact"
Code: [Select]
echo '{ "command": ["seek", '$currentFrame', "relative+exact"] }' | socat - /tmp/mpvsocket