Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vapoursynth support #172

Open
sosie-js opened this issue Jul 23, 2021 · 14 comments
Open

Vapoursynth support #172

sosie-js opened this issue Jul 23, 2021 · 14 comments

Comments

@sosie-js
Copy link

Hello Jaseg,

I tried to make you library work directly with vapoursynth but with no success.
With vspipe or directly with mpv standalone it works.

It simply output nothing when I use your library can you have a look at my repository python-mpv-vapoursynth-preview and disable the failsafe mode in vspreview/main.py ?

Thanks in advance.
SoSIE

@neinseg
Copy link

neinseg commented Jul 28, 2021

Hi there,

I'm not sure how the mpv binary's commandline parser for file URLs works, but I think it is possible that it works differently to how loadfile handles paths. The following seems to work for me, using the vapoursynth video filter:

player = mpv.MPV(vo='x11', log_handler=print, loglevel='debug')
player.loadfile('tests/test.webm', vf='vapoursynth=vpy_test.py')
player.wait_for_playback()

vpy_test.py:

#!/usr/bin/env python
import vapoursynth as vs
core = vs.get_core()
core.std.AddBorders(video_in, 10, 10, 20, 20).set_output()

Note that on my archlinux setup, I had to use a custom mpv build to get vapoursynth support, as the one from the arch package repo doesn't have it built-in.

@sosie-js
Copy link
Author

sosie-js commented Jul 28, 2021

Vielen Dank Herr neinseg, I didn't was aware about these extra params.
Concerning using a vs filter, I am not sure it usefull as we can uses vpy direct as video source.
Using backend 'pyvspipempv' renders but it is impossible to go back in the stream

        import mpv
        import subprocess
        script_path='vpy_test.py'
        player = mpv.MPV(config=True)
        @player.python_stream('foo')
        def reader():
	        with open('log.txt', 'ab+') as out:
		        p = subprocess.Popen(['/usr/bin/vspipe '+script_path+' -  --y4m' ], shell=True, stdout=subprocess.PIPE)
		        std_out, std_error = p.communicate()
	        # Write to the file
	        if std_error:
		        out.write( std_error )
	        yield std_out

        player.play('python://foo')
        player.wait_for_playback()

@neinseg
Copy link

neinseg commented Jul 28, 2021

Ah, I now understand what you're trying to do!

That's an interesting use of python streams. The reason seek does not work in this case is that vspipe simply outputs raw frame data. mpv does not store old frames, since that would be a very large amount of data.

The following works for me:

#!/usr/bin/env python3

import mpv

player = mpv.MPV(vo='x11', log_handler=print, loglevel='debug')
player.loadfile('vpy_test.py', demuxer_lavf_format='vapoursynth')
player.wait_for_playback()

vpy_test.py:

#!/usr/bin/env python
import vapoursynth as vs
core = vs.get_core()

clip = core.ffms2.Source("tests/test.webm")
clip.set_output()

Note that according to this mpv issue, libavformat does not load vapoursynth scripts by default. Instead, you have to explicitly pass that --demuxer-lavf-format parameter through libmpv.

With this solution, seeking works since vapoursynth is handled by ffmpeg itself.

@neinseg
Copy link

neinseg commented Jul 28, 2021

Fun fact: you can even directly feed vapoursynth python code through python-mpv, no need for a second file:

player = mpv.MPV(vo='x11', log_handler=print, loglevel='debug', loop=True)

@player.python_stream('vps-test')
def reader():
    yield b'''
#!/usr/bin/env python
import vapoursynth as vs
core = vs.get_core()

clip = core.ffms2.Source("tests/test.webm")
clip.set_output()
    '''

player.loadfile('python://vps-test', demuxer_lavf_format='vapoursynth')
player.wait_for_playback()

Over on my secret development repo you can even have a sneak preview of an upcoming very experimental convenience function that pipes a python function straight into vapoursynth using python-mpv, like this:

player = mpv.MPV(vo='x11')

# EXPERIMENTAL CODE, FEATURE NOT YET MERGED
@player.vapoursynth_stream()
def vps_test(filename):
    import vapoursynth as vs
    core = vs.get_core()

    clip = core.ffms2.Source(filename)
    clip.set_output()

vps_test("tests/test.webm")
player.wait_for_playback()

@sosie-js
Copy link
Author

sosie-js commented Jul 29, 2021

/\ _ /\
^ o ^
.\ _/. it smells the python-mpv-vsedit, ja/nein-seg isn't it?

Moreover it is a gate to handle any unhandled protocols . If this is multiplatform then we reached the graal, Danke schon Herr neinseg

@sosie-js
Copy link
Author

sosie-js commented Jul 29, 2021

In fact I can't use your library in your case which is in non stream (backend 'pyvspipempv' that uses libmpv too works, it's crazy!), something is broken

I have tested with the debug flag

import mpv
      script_path='vpy_test.py'
        try:
            #config=True,
            player = mpv.MPV(vo='x11', handler=print, loglevel='debug')
            #player.play("file://"+script_path) # FAILS unrecognized file format (reason 4), even if config is set
            # 'mpv --demuxer-lavf-format=vapoursynth  script_path' works like a charm
            player.loadfile(script_path, demuxer_lavf_format='vapoursynth')
            player.wait_for_playback()
        except NameError as err:
            print("Name error: {0}".format(err))
        except: # catch *all* exceptions
            e = sys.exc_info()[0]
            logging.error( "<p>Player Error: %s</p>" % e )

and especially with vo='X11', I get at least an error message
ERROR: <p>Player Error: <class 'AttributeError'></p>

when Inspecting with debugger it crashes directly in init
on the first line of
self.handle = _mpv_create()

I compiled from the sources mpv, my libmpv.so discovered by your script version is 1.109
with python 3.9.4 ,

mpv 0.33.0-209-gf2afae55e9 Copyright © 2000-2020 mpv/MPlayer/mplayer2 projects
 built on Sun Jul  4 14:32:32 CEST 2021
FFmpeg library versions:
   libavutil       56.70.100
   libavcodec      58.134.100
   libavformat     58.76.100
   libswscale      5.9.100
   libavfilter     7.110.100
   libswresample   3.9.100
FFmpeg version: n4.4-78-g031c0cb0b4

@neinseg
Copy link

neinseg commented Jul 29, 2021

The AttributeError is because of a tiny mistake in one line of your script. In this line:

            player = mpv.MPV(vo='x11', handler=print, loglevel='debug')

handler should be log_handler like this:

            player = mpv.MPV(vo='x11', log_handler=print, loglevel='debug')

@sosie-js
Copy link
Author

sosie-js commented Jul 29, 2021

Oh..thanks ^^'

Now after launching
python3 -m pdb run.py pylibmpv version.vpy

I get stuck with

> /python-mpv-vapoursynth-preview/run.py(2)<module>()
-> from vspreview import main
(Pdb) cont
Using backend 'pylibmpv' for playing '/python-mpv-vapoursynth-preview/version.vpy'
debug cplayer Run command: loadfile, flags=64, args=[url="/python-mpv-vapoursynth-preview/version.vpy", flags="replace", options="demuxer-lavf-format=vapoursynth"]
debug ytdl_hook loading @ytdl_hook.lua
debug stats reading options for stats
debug stats script-opts/stats.conf not found.
debug stats lua-settings/stats.conf not found.
debug cplayer Run command: define-section, flags=64, args=[name="input_stats", contents="i script-binding stats/display-stats\nI script-binding stats/display-stats-toggle\n", flags="default"]
debug cplayer Run command: enable-section, flags=64, args=[name="input_stats", flags="allow-hide-cursor+allow-vo-dragging"]
debug cplayer Run command: define-section, flags=64, args=[name="input_forced_stats", contents="", flags="force"]
debug cplayer Run command: enable-section, flags=64, args=[name="input_forced_stats", flags="allow-hide-cursor+allow-vo-dragging"]
debug auto_profiles loading mp.defaults
debug ytdl_hook reading options for ytdl_hook
debug ytdl_hook script-opts/ytdl_hook.conf not found.
debug ytdl_hook lua-settings/ytdl_hook.conf not found.
debug console reading options for console
debug console script-opts/console.conf not found.
debug console lua-settings/console.conf not found.
debug osd/libass ASS library version: 0x1501000 (runtime 0x1501000)
v osd/libass libass API version: 0x1501000
v osd/libass libass source: commit: 0.15.1-15-gd75ac2411ac52b5f5039f54962c6b5dba6b53b5a
debug auto_profiles loading @auto_profiles.lua
v osd/libass Shaper: FriBidi 1.0.5 (SIMPLE) HarfBuzz-ng 2.3.1 (COMPLEX)
v osd/libass Setting up fonts...
v osd/libass Using font provider fontconfig
v osd/libass Done.
debug auto_profiles Exiting...
v cplayer Done loading scripts.
debug global config path: 'watch_later' -> '-'
debug global config path: 'watch_later' -> '-'
v cplayer Setting option 'demuxer-lavf-format' = 'vapoursynth' (flags = 16)
v cplayer Running hook: ytdl_hook/on_load
v ytdl_hook ytdl:// hook
v ytdl_hook not a ytdl:// url
debug cplayer Run command: define-section, flags=64, args=[name="input_console", contents="", flags="default"]
debug cplayer Run command: enable-section, flags=64, args=[name="input_console", flags="allow-hide-cursor+allow-vo-dragging"]
debug cplayer Run command: define-section, flags=64, args=[name="input_forced_console", contents="", flags="force"]
debug cplayer Run command: enable-section, flags=64, args=[name="input_forced_console", flags="allow-hide-cursor+allow-vo-dragging"]
v bdmv/bluray Opening /python-mpv-vapoursynth-preview/version.vpy
v file Opening /python-mpv-vapoursynth-preview/version.vpy
debug file resize stream to 131072 bytes, drop 0 bytes
debug file Stream opened successfully.
v demux Trying demuxers for level=normal.
debug demux Trying demuxer: disc (force-level: normal)
debug demux Trying demuxer: edl (force-level: normal)
debug demux Trying demuxer: cue (force-level: normal)
debug demux Trying demuxer: rawaudio (force-level: normal)
debug demux Trying demuxer: rawvideo (force-level: normal)
debug demux Trying demuxer: mkv (force-level: normal)
debug demux Trying demuxer: lavf (force-level: normal)
v lavf Found 'vapoursynth' at score=100 size=0 (forced).

cplayer Gui does not appear, is there a special option to do so?
I mean it may require equivalents as in ~/.config/mpv/config file

[builtin-pseudo-gui]
terminal=no
force-window=yes
idle=once

[pseudo-gui]
player-operation-mode=pseudo-gui

@neinseg
Copy link

neinseg commented Jul 30, 2021

I have tried it and your code works on my system. Here are the scripts I used to test it. At the end of the post is a screenshot of the output I get and the log output.

#!/usr/bin/env python3

import mpv
import functools
import sys
import pickle

player = mpv.MPV(vo='x11', log_handler=print, loglevel='debug')
player.loadfile('vpy_test2.py', demuxer_lavf_format='vapoursynth')
player.wait_for_playback()

vpy_test2.py:

import vapoursynth as vs
from  vapoursynth import core

import json

#Python equivalent of package.path = package.path .. ";" ..script_dir.. rel_path
def includepath(rel_path=""):
                import os
                # Import scripts folder
                script_dir = os.path.dirname(__file__)
                dir=os.path.join(script_dir, rel_path)
                import sys
                sys.path.append(os.path.abspath(dir))

includepath()
from pprint import pprint
#print(core.version())
width=800
height=600
clip=core.std.BlankClip(width=width,height=height,format=vs.YUV420P8)

clip=core.text.FrameNum(clip,7,2)



clip=core.text.Text(clip,core.version(),9,2)
msg="Add the two lines to ~/.config/mpv/config:"+chr(13)+"[extension.vpy]"+chr(13)+"demuxer-lavf-format=vapoursynth"
format=clip[0].format
clip_infos = {
        'Width': clip.width,
        'Height': clip.height,
        'Frames': clip. num_frames,
        'FPS': clip.fps,
        'Format Name': format.name, #'YUV420P8'
        'Color Family': format.color_family, #'YUV'
        'Alpha': 'No',
        'Sample Type': format.sample_type , #'Integer',
        'Bits': format.bits_per_sample,
        'SubSampling W': format.subsampling_w,
        'SubSampling H': format.subsampling_h,
        'Planes':  format.num_planes
}
clip=core.text.Text(clip, "Frame informations:"+chr(13)+chr(13)+"Video:"+chr(13)+str(clip.width)+"x"+str(clip.height),4,2)
#clip=core.text.Text(clip, json.dumps(clip_infos, indent=4),5,1)
clip=core.text.Text(clip,"To play directly vapoursynth files,"+msg,1,2)
try:
  env = get_current_environment()
  with env.use():
    # Do stuff inside this env.
    #pprint(env)
    dummy=0
    #import web_pdb; web_pdb.set_trace()
except Exception:
  try:
    env = vpy_current_environment()
    with env.use():
      # Do stuff inside this env.
      #pprint(env)
      dummy=0
      #import web_pdb; web_pdb.set_trace()
  except Exception:
    env = globals()
    #pprint(env)
    dummy=0
    #import web_pdb; web_pdb.set_trace()
import mvsfunc as mvf
clip = mvf.ToYUV(clip,matrix = "709", css = "420", depth = 8)

#http://www.vapoursynth.com/doc/pythonreference.html#slicing-and-other-syntactic-sugar
#hide video trick, reduce to the min in time, shortcut for clip = clip.std.Trim(first=1, last=2)
#clip = clip[1:2]
#clip = core.resize.Bicubic(clip, width=10,height=10)
clip.set_output()

Click here to view Log

debug cplayer Run command: loadfile, flags=64, args=[url="vpy_test2.py", flags="replace", options="demuxer-lavf-format=vapoursynth"]                                                     [9/1803]debug ytdl_hook loading @ytdl_hook.lua
debug auto_profiles loading @auto_profiles.lua
debug stats loading @stats.lua
debug console loading @console.lua
debug auto_profiles Exiting...
debug ytdl_hook reading options for ytdl_hook
debug ytdl_hook script-opts/ytdl_hook.conf not found.
debug ytdl_hook lua-settings/ytdl_hook.conf not found.
debug stats reading options for stats
debug stats script-opts/stats.conf not found.                                                                                                                                                    debug stats lua-settings/stats.conf not found.
debug console reading options for console
debug console script-opts/console.conf not found.
debug console lua-settings/console.conf not found.
v cplayer Done loading scripts.
debug global config path: 'watch_later' -> '-'
debug global config path: 'watch_later' -> '-'
v cplayer Setting option 'demuxer-lavf-format' = 'vapoursynth' (flags = 16)
v cplayer Running hook: ytdl_hook/on_load
v ytdl_hook ytdl:// hook
debug cplayer Run command: define-section, flags=64, args=[name="input_stats", contents="i script-binding stats/display-stats\nI script-binding stats/display-stats-toggle\n", flags="default"]  v ytdl_hook not a ytdl:// url
debug cplayer Run command: enable-section, flags=64, args=[name="input_stats", flags="allow-hide-cursor+allow-vo-dragging"]                                                                      debug osd/libass ASS library version: 0x1500000 (runtime 0x1501000)
v osd/libass libass API version: 0x1501000
v osd/libass libass source: commit: 0.15.1-0-g5447214643eacef71776350e779adf4b6c07bb3b-dirty
v osd/libass Shaper: FriBidi 1.0.10 (SIMPLE) HarfBuzz-ng 2.8.2 (COMPLEX)
v osd/libass Setting up fonts...
v osd/libass Using font provider fontconfig
v osd/libass Done.
debug cplayer Run command: define-section, flags=64, args=[name="input_forced_stats", contents="", flags="force"]                                                                                debug cplayer Run command: enable-section, flags=64, args=[name="input_forced_stats", flags="allow-hide-cursor+allow-vo-dragging"]                                                               v ifo_dvdnav Opening vpy_test2.py
debug cplayer Run command: define-section, flags=64, args=[name="input_console", contents="", flags="default"]                                                                                   v bdmv/bluray Opening vpy_test2.py
debug cplayer Run command: enable-section, flags=64, args=[name="input_console", flags="allow-hide-cursor+allow-vo-dragging"]                                                                    v file Opening vpy_test2.py
debug file resize stream to 131072 bytes, drop 0 bytes
debug cplayer Run command: define-section, flags=64, args=[name="input_forced_console", contents="", flags="force"]                                                                              debug cplayer Run command: enable-section, flags=64, args=[name="input_forced_console", flags="allow-hide-cursor+allow-vo-dragging"]                                                             debug file Stream opened successfully.
v demux Trying demuxers for level=normal.
debug demux Trying demuxer: disc (force-level: normal)
debug demux Trying demuxer: edl (force-level: normal)
debug demux Trying demuxer: cue (force-level: normal)
debug demux Trying demuxer: rawaudio (force-level: normal)
debug demux Trying demuxer: rawvideo (force-level: normal)
debug demux Trying demuxer: mkv (force-level: normal)
debug demux Trying demuxer: libarchive (force-level: normal)
debug demux Trying demuxer: lavf (force-level: normal)
v lavf Found 'vapoursynth' at score=100 size=0 (forced).
debug ffmpeg/demuxer vapoursynth: VS format YUV420P8 -> pixfmt yuv420p
v lavf avformat_find_stream_info() finished after 2227 bytes.
v demux Detected file format: vapoursynth (libavformat)
v cplayer Opening done: vpy_test2.py
v find_files Loading external files in .
v cplayer Running hook: ytdl_hook/on_preloaded
v lavf select track 0
info cplayer  (+) Video --vid=1 (wrapped_avframe 800x600)
v vo/x11/x11 X11 opening display: 172.30.128.1:0
debug vo/x11/x11 X11 running at 5280x2560 ("172.30.128.1:0" => remote display)
debug vo/x11/x11 Detected wm supports NetWM.
debug vo/x11/x11 Detected wm supports ABOVE state.
debug vo/x11/x11 Detected wm supports BELOW state.
v vo/x11/x11 Display 0 (default): [0, 0, 5280, 2560] @ 0.000000 FPS
v vo/x11 selected visual: 33
warn vo/x11 Warning: this legacy VO has bad performance. Consider fixing your graphics drivers, or not forcing the x11 VO.                                                                       v vd Container reported FPS: 0.000000
v vd Codec list:
v vd     wrapped_avframe - AVPacket to AVFrame passthrough
v vd Opening decoder wrapped_avframe
v vd No hardware decoding requested.
v vd Using software decoding.
v vd Detected 12 logical cores.
v vd Requesting 13 threads for decoding.
v vd Selected codec: wrapped_avframe (AVPacket to AVFrame passthrough)
v vf User filter list:
v vf   (empty)
v cplayer Starting playback...
v vd Using software decoding.
v vd Decoder format: 800x600 [0:1] yuv420p auto/auto/auto/auto/auto CL=unknown
v vf [in] 800x600 yuv420p bt.709/bt.709/bt.1886/limited/display SP=1.000000 CL=mpeg2/4/h264
v vf [userdeint] 800x600 yuv420p bt.709/bt.709/bt.1886/limited/display SP=1.000000 CL=mpeg2/4/h264                                                                                               v vf [userdeint] (disabled)
v vf [autorotate] 800x600 yuv420p bt.709/bt.709/bt.1886/limited/display SP=1.000000 CL=mpeg2/4/h264                                                                                              v vf [autorotate] (disabled)
v vf [convert] 800x600 yuv420p bt.709/bt.709/bt.1886/limited/display SP=1.000000 CL=mpeg2/4/h264                                                                                                 v vf [convert] (disabled)
v vf [out] 800x600 yuv420p bt.709/bt.709/bt.1886/limited/display SP=1.000000 CL=mpeg2/4/h264
info cplayer VO: [x11] 800x600 yuv420p
v cplayer VO: Description: X11 (software scaling)
v vo/x11 reconfig to 800x600 yuv420p bt.709/bt.709/bt.1886/limited/display SP=1.000000 CL=mpeg2/4/h264                                                                                           debug vo/x11 screen size: 1440x2520
warn vo/x11 Shared memory not supported
warn vo/x11 Reverting to normal Xlib
v vo/x11 Not using SHM.
warn vo/x11 Shared memory not supported
warn vo/x11 Reverting to normal Xlib
v vo/x11 Not using SHM.
v vo/x11 Using mp format: bgr0
v vo/x11 Window size: 800x600 (Borders: l=0 t=0 r=0 b=0)
v vo/x11 Video source: 800x600 (1:1)
v vo/x11 Video display: (0, 0) 800x600 -> (0, 0) 800x600
v vo/x11 Video scale: 1.000000/1.000000
v vo/x11 OSD borders: l=0 t=0 r=0 b=0
v vo/x11 Video borders: l=0 t=0 r=0 b=0
v vo/x11 using 9 threads for scaling
v vo/x11 Using zimg.
v vo/x11 Using mp format: bgr0
v vo/x11 Window size: 800x600 (Borders: l=0 t=0 r=0 b=0)
v vo/x11 Video source: 800x600 (1:1)
v vo/x11 Video display: (0, 0) 800x600 -> (0, 0) 800x600
v vo/x11 Video scale: 1.000000/1.000000
v vo/x11 OSD borders: l=0 t=0 r=0 b=0
v vo/x11 Video borders: l=0 t=0 r=0 b=0
v cplayer first video frame after restart shown
debug cplayer starting video playback
v cplayer playback restart complete @ 0.000000, audio=eof, video=playing
v vo/x11/x11 Disabling screensaver.

Capture

@sosie-js
Copy link
Author

sosie-js commented Jul 30, 2021

hum, your example is confusing for two reasons,

  • first script have to be named 'vpy_test2.py' whereas second is a vapoursynth one , so has to be renamed from 'vpy_test2.py' to 'vpy_test2.vpy' meaning player.loadfile('vpy_test2.vpy', demuxer_lavf_format='vapoursynth')
    instead
  • you are using the mpv module version, that can be installed witth pip / pip3 here
    On my side it's an outdated one
$ sudo pip3 install mpv
[sudo] Mot de passe de sosie :           
Collecting mpv
  Downloading mpv-0.1.tar.gz (6.2 kB)
Using legacy 'setup.py install' for mpv, since package 'wheel' is not installed.
Installing collected packages: mpv
    Running setup.py install for mpv ... done
Successfully installed mpv-0.1

Maybe you did not seen I gave a hint by providing my secret hijack and magic includepath
from my secret service ^o^

#Python equivalent of package.path = package.path .. ";" ..script_dir.. rel_path
def includepath(rel_path=""):
                import os
                # Import scripts folder
                script_dir = os.path.dirname(__file__)
                dir=os.path.join(script_dir, rel_path)
                import sys
                sys.path.append(os.path.abspath(dir))

includepath()

if you do not do so be sure your travel will have flight problems:
Here is what I have with mpv-0.1

$ python3 -m pdb vpy_test2.py
> /tests/python-mpv-vapoursynth-preview/vpy_test2.py(3)<module>()
-> import mpv
(Pdb) cont
Exception in callback MPV.__init__.<locals>.mpv_event_extractor() at /usr/local/lib/python3.9/site-packages/mpv.py:276
handle: <Handle MPV.__init__.<locals>.mpv_event_extractor() at /usr/local/lib/python3.9/site-packages/mpv.py:276>
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/mpv.py", line 254, in _event_generator
    raise StopIteration()
StopIteration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "/usr/local/lib/python3.9/site-packages/mpv.py", line 278, in mpv_event_extractor
    for event in _event_generator(self.handle):
RuntimeError: generator raised StopIteration
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/pdb.py", line 1705, in main
    pdb._runscript(mainpyfile)
  File "/usr/local/lib/python3.9/pdb.py", line 1573, in _runscript
    self.run(statement)
  File "/usr/local/lib/python3.9/bdb.py", line 580, in run
    exec(cmd, globals, locals)
  File "<string>", line 1, in <module>
  File "/python-mpv-vapoursynth-preview/vpy_test2.py", line 3, in <module>
    import mpv
  File "/usr/local/lib/python3.9/site-packages/mpv.py", line 302, in __init__
    _mpv_set_option_string(self.handle, k.replace('_', '-').encode(), istr(v).encode())
  File "/usr/local/lib/python3.9/site-packages/mpv.py", line 174, in wrapper
    ErrorCode.raise_for_ec(func, *args)
  File "/usr/local/lib/python3.9/site-packages/mpv.py", line 59, in raise_for_ec
    raise ex(ec, *args)
AttributeError: ('mpv option does not exist', -5, <MpvHandle object at 0x7f0e6e725bc0>, b'log-handler', b'<built-in function print>')
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> /usr/local/lib/python3.9/site-packages/mpv.py(59)raise_for_ec()
-> raise ex(ec, *args)

So before import mpv (looking for the first mpv.py in the path) , to ensure it will use your last mpv.py, aside vpy_test2.py and vpy_test2.vpy
we call the magic includepath() i teleported in the vpy_test2.py.
And now python3 vpy_test2.vpy works MONSIEUR! (APPLAUDE)

So what happens? Why python3 run.py pylibmpv vpy_test2.vpy gaves me a black screen? it smell a problem of path...
image

@neinseg
Copy link

neinseg commented Jul 30, 2021

first script have to be named 'vpy_test2.py' whereas second is a vapoursynth one , so has to be renamed from 'vpy_test2.py' to 'vpy_test2.vpy' meaning player.loadfile('vpy_test2.vpy', demuxer_lavf_format='vapoursynth')
instead

You could also rename it, I am just not used to vapoursynth conventions and it seems vapoursynth itself does not care: The file loaded just fine.

$ sudo pip3 install mpv

The pip package is called python-mpv, not just mpv. The mpv pip package is a very old copy of my one, but is not owned by me. I will try to contact them so they can perhaps take down that outdated copy.

So what happens? Why python3 run.py pylibmpv vpy_test2.vpy gaves me a black screen? it smell a problem of path...

Could you please post the full terminal output of that here? Like, from how you call it to the very last line it outputs?

Could you also please try the code I posted in this post and tell me what happens? That would help narrow down if the issue is somewhere in the python code or the libmpv installation. You can just paste the python test code in the first snipped into a python shell.

@sosie-js
Copy link
Author

sosie-js commented Jul 31, 2021

@sosie-js
Copy link
Author

sosie-js commented Aug 2, 2021

Guess what? it's simply making mpv unstable.. I grouped all the code in one file run.py (Goldman version)
and then trigger it multiples times python3 run.py pylibmpv version.vpy to crash or abort the process randomly.

FFmpeg secret bridge works as well ; https://gist.github.com/sosie-js/d4a63f16bda4589176ed19bb6b4f2eab
hacking it to lavf such as ffmpeg -f vapoursynth -filter_complex "movie='vpy_test2.vpy'[in1];[in1][out]" -loglevel fatal -hide_banner -nostdin -f yuv4mpegpipe -strict -1 -pix_fmt yuv420p - | mpv -, no :-(

run.py: - includes backend pyrawpipempv, ie your hacky vapoursynth code injection to mpv through a pipe (sucks, froze on the black screen, do no crash like than pylibmpv)
https://github.com/sosie-js/python-mpv-vapoursynth-preview/blob/master/vspreview/main.py

@sosie-js
Copy link
Author

sosie-js commented Aug 7, 2021

Now I restricted the test to libmpv backend. The suprize is that this command python3 version_pylibmpv.py version.vpy
triggers all files test.webm, the .py , then the wished version;vpy without rendering it to finish on , "no file.mpv" black screen.
with version_pylibmpv.py aside version pylibmpv of https://github.com/sosie-js/python-mpv-vapoursynth-preview/

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import logging
import os
from   pathlib  import * #Path
import sys

import mpv
import functools
import pickle


import argparse
from argparse import ArgumentParser


import vapoursynth as     vs

version='JJGoldmanPlus'
backend='pylibmpv'
script_path=''
folder = Path(__file__).parent
script_path=str(folder.joinpath(script_path))

def install_custom_log():
    logging.basicConfig(format='{asctime}: {levelname}: {message}',
                        style='{', level=logging.DEBUG)
    logging.Formatter.default_msec_format = '%s.%03d'


def create_parser():

    parser = ArgumentParser(
        description="Specify the vapoursynth with script_path to use"
    )

    parser.add_argument('script_path', help='Path to Vapoursynth script',
                        type=Path, nargs='?')
   
    return parser


def main():
    
    install_custom_log()

    check_versions()

    args = create_parser().parse_args()

    if args.script_path is None:
        print('python-mpv-vapoursynth-preview ('+version+' version) require argument, -h for help')
        sys.exit(1)

    script_path = args.script_path.absolute() #dont follow links like resolve()
    if not script_path.exists():
        print('Script path is invalid.')
        sys.exit(1)


    #convert pathlib.PosixPath to str so  script_path.encode() will work
    script_path=str(script_path)

    print(version+" use backend '"+backend + "' for playing '"+script_path+"'")
    

def check_versions() -> bool:
    from pkg_resources import get_distribution
    from platform import python_version

    failed = False

    if sys.version_info < (3, 9, 0, 'final', 0):
        logging.warning('VSPreview is not tested on Python versions prior to 3.9, but you have {} {}. Use at your own risk.'
                        .format(python_version(), sys.version_info.releaselevel))
        failed = True

    #if get_distribution('PyQt5').version < '5.15':
     #   logging.warning('VSPreview is not tested on PyQt5 versions prior to 5.15, but you have {}. Use at your own risk.'
     #                   .format(get_distribution('PyQt5').version))
     #   failed = True

    if vs.core.version_number() < 53:
        logging.warning('VSPreview is not tested on VapourSynth versions prior to 53, but you have {}. Use at your own risk.'
                        .format(vs.core.version_number()))
        failed = True

    return not failed



def score(loglevel, component, message):
    score='[{}] {}: {}'.format(loglevel, component, message)
    print(score)
    scores.write(score+chr(13))


main()

try:
    with open('log_topgun.txt', 'a+') as scores:
        scores.write("----- game starts with "+__file__+"---"+chr(13))
        player = mpv.MPV(vo='x11', log_handler=print, loglevel='debug', player_operation_mode='pseudo-gui', input_default_bindings=True, input_vo_keyboard=True)
        #scripts='debug.lua', script_opts='debug-scriptpath='+script_path) #config=True,
        #player.play("file://"+script_path) # FAILS unrecognized file format (reason 4), even if config is s
        player.loadfile(script_path, demuxer_lavf_format='vapoursynth')
        player.wait_for_playback()
        scores.write("----- game over ---"+chr(13))
except NameError as err:
    print("Name error: {0}".format(err))
except: # catch *all* exceptions
    e = sys.exc_info()[0]
    logging.error( "<p>Player Error: %s</p>" % e )

Python or libmpv stack overflow leading to search for fie in the path what do you think about it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants