GithubHelp home page GithubHelp logo

jaseg / python-mpv Goto Github PK

View Code? Open in Web Editor NEW
532.0 18.0 67.0 553 KB

Python interface to the awesome mpv media player

Home Page: https://git.jaseg.de/python-mpv.git

License: Other

Python 99.38% Shell 0.62%
media video audio python ffi bindings gui pillow multimedia multimedia-player

python-mpv's Introduction

python-mpv

python-mpv is a ctypes-based python interface to the mpv media player. It gives you more or less full control of all features of the player, just as the lua interface does.

Installation

pip install mpv

...though you can also realistically just copy mpv.py into your project as it's all nicely contained in one file.

Requirements

libmpv

libmpv.so either locally (in your current working directory) or somewhere in your system library search path. This module is somewhat lenient as far as libmpv versions are concerned but since libmpv is changing quite frequently you'll only get all the newest features when using an up-to-date version of this module. The unit tests for this module do some basic automatic version compatibility checks. If you discover anything missing here, please open an issue or submit a pull request on github.

On Windows you can place libmpv anywhere in your %PATH% (e.g. next to python.exe) or next to this module's mpv.py. Before falling back to looking in the mpv module's directory, python-mpv uses the DLL search order built into ctypes, which is different to the one Windows uses internally. Consult this stackoverflow post for details.

Python >= 3.9

We only support python stable releases from the last couple of years. We only test the current stable python release. If you find a compatibility issue with an older python version that still has upstream support (that is less than about four years old), feel free to open an issue and we'll have a look.

Supported Platforms

Linux, Windows and OSX all seem to work mostly fine. For some notes on the installation on Windows see this comment. Shared library handling is quite bad on windows, so expect some pain there. On OSX there seems to be some bug int the event logic. See issue 36 and issue 61 for details. Creating a pyQT window and having mpv draw into it seems to be a workaround (about 10loc), but in case you want this fixed please weigh in on the issue tracker since right now there is not many OSX users.

Usage

import mpv
player = mpv.MPV(ytdl=True)
player.play('https://youtu.be/DOmdB7D-pUU')
player.wait_for_playback()

python-mpv mostly exposes mpv's built-in API to python, adding only some porcelain on top. Most "input commands" are mapped to methods of the MPV class. Check out these methods and their docstrings in the source for things you can do. Additional controls and status information are exposed through MPV properties. These can be accessed like player.metadata, player.fullscreen and player.loop_playlist.

Threading

The mpv module starts one thread for event handling, since MPV sends events that must be processed quickly. The event queue has a fixed maximum size and some operations can cause a large number of events to be sent.

If you want to handle threading yourself, you can pass start_event_thread=False to the MPV constructor and manually call the MPV object's _loop function. If you have some strong need to not use threads and use some external event loop (such as asyncio) instead you can do that, too with some work. The API of the backend C libmpv has a function for producing a sort of event file descriptor for a handle. You can use that to produce a file descriptor that can be passed to an event loop to tell it to wake up the python-mpv event handler on every incoming event.

All API functions are thread-safe. If one is not, please file an issue on github.

Advanced Usage

Logging, Properties, Python Key Bindings, Screenshots and youtube-dl

#!/usr/bin/env python3
import mpv

def my_log(loglevel, component, message):
    print('[{}] {}: {}'.format(loglevel, component, message))

player = mpv.MPV(log_handler=my_log, ytdl=True, input_default_bindings=True, input_vo_keyboard=True)

# Property access, these can be changed at runtime
@player.property_observer('time-pos')
def time_observer(_name, value):
    # Here, _value is either None if nothing is playing or a float containing
    # fractional seconds since the beginning of the file.
    print('Now playing at {:.2f}s'.format(value))

player.fullscreen = True
player.loop_playlist = 'inf'
# Option access, in general these require the core to reinitialize
player['vo'] = 'gpu'

@player.on_key_press('q')
def my_q_binding():
    print('THERE IS NO ESCAPE')

@player.on_key_press('s')
def my_s_binding():
    pillow_img = player.screenshot_raw()
    pillow_img.save('screenshot.png')

player.play('https://youtu.be/DLzxrzFCyOs')
player.wait_for_playback()

del player

Skipping silence using libav filters

The following code uses the libav silencedetect filter to skip silence at the beginning of a file. It works by loading the filter, then parsing its output from mpv's log. Thanks to Sean DeNigris on github (#202) for the original code!

#!/usr/bin/env python3
import sys
import mpv

p = mpv.MPV()
p.play(sys.argv[1])

def skip_silence():
    p.set_loglevel('debug')
    p.af = 'lavfi=[silencedetect=n=-20dB:d=1]'
    p.speed = 100
    def check(evt):
        toks = evt['event']['text'].split()
        if 'silence_end:' in toks:
            return float(toks[2])
    p.time_pos = p.wait_for_event('log_message', cond=check)
    p.speed = 1
    p.af = ''

skip_silence()
p.wait_for_playback()

Video overlays

#!/usr/bin/env python3
import time
from PIL import Image, ImageDraw, ImageFont
import mpv

player = mpv.MPV()

player.loop = True
player.play('test.webm')
player.wait_until_playing()

font = ImageFont.truetype('DejaVuSans.ttf', 40)

while not player.core_idle:

    time.sleep(0.5)
    overlay = player.create_image_overlay()

    for pos in range(0, 500, 5):
        ts = player.time_pos
        if ts is None:
            break

        img = Image.new('RGBA', (400, 150),  (255, 255, 255, 0))
        d = ImageDraw.Draw(img)
        d.text((10, 10), 'Hello World', font=font, fill=(0, 255, 255, 128))
        d.text((10, 60), f't={ts:.3f}', font=font, fill=(255, 0, 255, 255))

        overlay.update(img, pos=(2*pos, pos))
        time.sleep(0.05)

    overlay.remove()

Playlist handling

#!/usr/bin/env python3
import mpv

player = mpv.MPV(ytdl=True, input_default_bindings=True, input_vo_keyboard=True)

player.playlist_append('https://youtu.be/PHIGke6Yzh8')
player.playlist_append('https://youtu.be/Ji9qSuQapFY')
player.playlist_append('https://youtu.be/6f78_Tf4Tdk')

player.playlist_pos = 0

while True:
    # To modify the playlist, use player.playlist_{append,clear,move,remove}. player.playlist is read-only
    print(player.playlist)
    player.wait_for_playback()

Directly feeding mpv data from python

#!/usr/bin/env python3
import mpv

player = mpv.MPV()
@player.python_stream('foo')
def reader():
    with open('test.webm', 'rb') as f:
        while True:
            yield f.read(1024*1024)

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

Using external subtitles

The easiest way to load custom subtitles from a file is to pass the --sub-file option to the loadfile call:

#!/usr/bin/env python3
import mpv

player = mpv.MPV()
player.loadfile('test.webm', sub_file='test.srt')
player.wait_for_playback()

Note that you can also pass many other options to loadfile. See the mpv docs for details.

If you want to add subtitle files or streams at runtime, you can use the sub-add command. sub-add can only be called once the player is done loading the file and starts playing. An easy way to wait for this is to wait for the core-idle property.

#!/usr/bin/env python3
import mpv

player = mpv.MPV()
player.play('test.webm')
player.wait_until_playing()
player.sub_add('test.srt')
player.wait_for_playback()

Using MPV's built-in GUI

python-mpv is using mpv via libmpv. libmpv is meant for embedding into other applications and by default disables most GUI features such as the OSD or keyboard input. To enable the built-in GUI, use the following options when initializing the MPV instance. See Issue 102 for more details

# Enable the on-screen controller and keyboard shortcuts
player = mpv.MPV(input_default_bindings=True, input_vo_keyboard=True, osc=True)

# Alternative version using the old "floating box" style on-screen controller
player = mpv.MPV(player_operation_mode='pseudo-gui',
                 script_opts='osc-layout=box,osc-seekbarstyle=bar,osc-deadzonesize=0,osc-minmousemove=3',
                 input_default_bindings=True,
                 input_vo_keyboard=True,
                 osc=True)

PyQT embedding

#!/usr/bin/env python3
import mpv
import sys

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class Test(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.container = QWidget(self)
        self.setCentralWidget(self.container)
        self.container.setAttribute(Qt.WA_DontCreateNativeAncestors)
        self.container.setAttribute(Qt.WA_NativeWindow)
        player = mpv.MPV(wid=str(int(self.container.winId())),
                vo='x11', # You may not need this
                log_handler=print,
                loglevel='debug')
        player.play('test.webm')

app = QApplication(sys.argv)

# This is necessary since PyQT stomps over the locale settings needed by libmpv.
# This needs to happen after importing PyQT before creating the first mpv.MPV instance.
import locale
locale.setlocale(locale.LC_NUMERIC, 'C')
win = Test()
win.show()
sys.exit(app.exec_())

PyGObject embedding

#!/usr/bin/env python3
import gi

import mpv

gi.require_version('Gtk', '3.0')
from gi.repository import Gtk


class MainClass(Gtk.Window):

    def __init__(self):
        super(MainClass, self).__init__()
        self.set_default_size(600, 400)
        self.connect("destroy", self.on_destroy)

        widget = Gtk.Frame()
        self.add(widget)
        self.show_all()

        # Must be created >after< the widget is shown, else property 'window' will be None
        self.mpv = mpv.MPV(wid=str(widget.get_property("window").get_xid()))
        self.mpv.play("test.webm")

    def on_destroy(self, widget, data=None):
        self.mpv.terminate()
        Gtk.main_quit()


if __name__ == '__main__':
    # This is necessary since like Qt, Gtk stomps over the locale settings needed by libmpv.
    # Like with Qt, this needs to happen after importing Gtk but before creating the first mpv.MPV instance.
    import locale
    locale.setlocale(locale.LC_NUMERIC, 'C')

    application = MainClass()
    Gtk.main()

Using OpenGL from PyGObject

Just like it is possible to render into a GTK widget through X11 windows, it also is possible to render into a GTK widget using OpenGL through this python API.

Using OpenGL from PyQt5/QML

Robozman has mangaed to make mpv render into a PyQt5/QML widget using OpenGL through this python API.

Using mpv inside imgui inside OpenGL via GLFW

dfaker has written a demo (link) that uses mpv to render video into an imgui UI running on an OpenGL context inside GLFW. Check out their demo to see how to integrate with imgui/OpenGL and how to access properties and manage the lifecycle of an MPV instance.

Running tests

Use pytest to run tests.

Coding Conventions

The general aim is PEP 8, with liberal application of the "consistency" section. 120 cells line width. Four spaces. No tabs. Probably don't bother making pure-formatting PRs except if you think it really helps readability or it really irks you if you don't.

License

python-mpv inherits the underlying libmpv's license, which can be either GPLv2 or later (default) or LGPLv2.1 or later. For details, see the mpv copyright page.

python-mpv's People

Contributors

baldurmen avatar cosven avatar cyates559 avatar dfaker avatar frechdachs avatar hatzel avatar hixz00 avatar jaseg avatar matt-deacalion avatar mcsinyx avatar mgorny avatar naglis avatar paride avatar rien333 avatar ripdog avatar robozman avatar sdaqo avatar snoopj avatar trin94 avatar vilius-g avatar yostealth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-mpv's Issues

input_default_bindings not working on macOS

Hello,

Time for another macOS related issue ( :-[ ). As explained in #61, an extra QT-Window needs to be created for python-mpv to work on macOS.

If I now take the PyQT embedding example from the README and add input_default_bindings=True, input_vo_keyboard=True to the MPV instantiation, I would expect mpv-commands such as space (for pausing) or o (for time-display) to work.
On linux, it does indeed work.
On macOS however, nothing happens.

Do you have a suggestion why this might be happening? (PyQT not forwarding keypress-events, ...)

Possibility to get this working under Windows

Is it possible to get this working with lachs0r's Windows build of libmpv? (It's included in the Dev package).

I've tried changing every CDDL to WinDLL and every CFUNCTYPE to WINFUNCTYPE but it did not work.

I get the following exception:

Traceback (most recent call last):
  File "E:\libmpv-test\start.py", line 4, in <module>
    mp = mpv.MPV()
  File "E:\libmpv-test\mpv.py", line 271, in __init__
    self._event_fd = _mpv_get_wakeup_pipe(self.handle)
  File "E:\libmpv-test\mpv.py", line 172, in wrapper
    return func(*args)
ValueError: Procedure probably called with too many arguments (4 bytes in excess)

while executing the following code:

import mpv
m = mpv.MPV()

I would appreciate any help.

Add Youtube DL options support

You could add Youtube DL options such as changing the video format or even give options using --ytdl-raw-options, it would be very useful for certain scripts to choose predefined formats.

Sorry for my bad English.

Undefined symbol: mpv_create_client

Hi, i'm trying to import "mpv" . But i get the following errors:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/dist-packages/mpv.py", line 319, in <module>
    _handle_func('mpv_create_client',           [c_char_p],                                 MpvHandle, notnull_errcheck)
  File "/usr/local/lib/python3.4/dist-packages/mpv.py", line 280, in _handle_func
    func = getattr(backend, name)
  File "/usr/lib/python3.4/ctypes/__init__.py", line 364, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib/python3.4/ctypes/__init__.py", line 369, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /usr/lib/arm-linux-gnueabihf/libmpv.so.1: undefined symbol: mpv_create_client

How can i solve this problem?
Tnx

Incorrect type casting producing garbage on property access when running on i386

The speed option is described in mpv(1) section OPTIONS, subsection Playback Control.

I tried to used both property and option access but neither of them works:

Property access:

Traceback (most recent call last):
  File "./comp", line 370, in <module>
    comp.mp.speed *= 0.9091
  File "/home/cnx/.local/lib/python3.5/site-packages/mpv.py", line 1033, in __setattr__
    self._set_property(_py_to_mpv(name), value)
  File "/home/cnx/.local/lib/python3.5/site-packages/mpv.py", line 1025, in _set_property
    _mpv_set_property_string(self.handle, ename, _mpv_coax_proptype(value))
  File "/home/cnx/.local/lib/python3.5/site-packages/mpv.py", line 105, in raise_for_ec
    raise ex(ec, *args)
TypeError: ('Tried to get/set mpv property using wrong format, or passed invalid value', -9, (<MpvHandle object at 0xacbcfb24>, b'speed', b'0.0'))

Option access:

Traceback (most recent call last):
  File "./comp", line 370, in <module>
    comp.mp['speed'] *= 0.9091
  File "/home/cnx/.local/lib/python3.5/site-packages/mpv.py", line 1055, in __setitem__
    return self._set_property(prefix+name, value)
  File "/home/cnx/.local/lib/python3.5/site-packages/mpv.py", line 1025, in _set_property
    _mpv_set_property_string(self.handle, ename, _mpv_coax_proptype(value))
  File "/home/cnx/.local/lib/python3.5/site-packages/mpv.py", line 105, in raise_for_ec
    raise ex(ec, *args)
TypeError: ('Tried to get/set mpv property using wrong format, or passed invalid value', -9, (<MpvHandle object at 0xacc3eb24>, b'options/speed', b'0.0'))

I'm using python-mpv 0.3.4 on Debian testing.

Unit tests hanging somewhere on (my particular instance of) Archlinux

So it seems that for some reason on my particular arch setup, calls to set options via both mpv_set_option_string and node-based mpv_set_property with option/ prefix ends up in a call to mpv_terminate_destroy that hangs indefinitely supposedly due to some half-initialized client clinging to the handle.

Next steps are to reproduce this problem on another distro (fedora/debian in my case) as well as a fresh mpv build on arch and in case this is reproducible debug the hell out of it and find out where I messed up.

Fixes for use with Python2

For those who, like me, are stuck with Python 2 at the moment, and trying to make this work...

Initially, mpv wouldn't event import, but that was easy enough to fix:

  • comment out the asyncio import (as it's not used any more)
  • remove the 'daemon=True' kwarg in self._event_thread
  • add a call to 'self._event_thread.setDaemon(True)' after that line

From there on, mpv imports, loads videos and most methods work:
command, terminate, seek, frame_step, loadfile/play, toggle_osd, show_text for example.
Haven't tested them all, but certainly enough to go by...

Thanks for these bindings !

Does not support Windows

Contrary to its PyPI classifiers python-mpv does not support Windows due to its usage of unix sockets.

Windows can be supported however with the usage of a named pipe via pypiwin32. Apps such as web3 support both this way.

Tried implementing it myself but hit a stumbling block when trying to understand JSONBaseProvider used in the aforementioned app.

can not set class object instance method as handler

I have a piece of code like this:

import mpv

player = mpv.MPV(ytdl=True, input_default_bindings=True, input_vo_keyboard=True)

class T(object):
    def t(self, *args, **kw):
       print(args, kw)

t =  T()
# Property access, these can be changed at runtime
player.observe_property('time-pos', t.t)   # this will raise AttributeError

It will try to set observed_mpv_properties attr on handler, but as the python docs say:

setting method attributes on bound methods is disallowed. Attempting to set an attribute on a method results in an AttributeError being raised.

multiple external-file not supported?

While we can pass multiple external-file arguments to the mpv itself like this:

mpv 1.mov --external-file=2.mov --external-file=3.mov --lavfi-complex="[vid1][vid2][vid3]..."

There is no visible way to do it with this app. I also tried the following:

player["external-file"] = ["2.mov","3.mov"]

which does not throw an error, but won't take the inputs either.

Fullscreen property not working

See #41. Setting fullscreen doesn't work from either python or lua. The vo seems to do the resize op but the window doesn't actually change.

app won't close pressing title bar close button

In Windows 10 how can I make the app close when the close button of the title bar is pressed?

import sys, mpv

player = mpv.MPV(config='yes')

if len(sys.argv) == 1:
    sys.argv = ["",
               r"D:\Temp\StaxRip\doku.mkv",
               r"D:\Temp\StaxRip\Eli.mp4",
               r"D:\Temp\StaxRip\atmos.mkv"]

for file in sys.argv[1:]:
    player.playlist_append(file)

player.playlist_pos = 0

while True:
    player.wait_for_playback()

Property observer doesn't seem to receive correct values

Hi,

I'm running python-mpv 0.3.7 with mpv-1.dll x32 with Python 3.5.1 x32 on Windows 10 x64

The following snippet returns strange values:

import mpv

player = mpv.MPV(ytdl=True)
player['vid'] = 'no'

@player.property_observer('time-pos')
def time_observer(_name, value):
  # Here, _value is either None if nothing is playing or a float containing
  # fractional seconds since the beginning of the file.
  # print('Now playing at {:.2f}s'.format(value))
  print('Now playing at ', str(value))

player.play('https://youtube.com/watch?v=vveaDYzgYxo')
player.wait_for_playback()

The output is:

Now playing at  1.3993628587e-314
Now playing at  1.5300098963e-314
Now playing at  1.2789014024e-314
Now playing at  1.3351258016e-314
Now playing at  4.91624003e-316
Now playing at  2.097007171e-314
Now playing at  1.2340848504e-314
Now playing at  4.84697793e-315
Now playing at  8.445882796e-315
Now playing at  1.8048847433e-314
Now playing at  1.636483184e-315
Now playing at  1.0954251585e-314
Now playing at  8.54366437e-315
Now playing at  1.5329976654e-314
Now playing at  6.927552357e-315
Now playing at  8.406498545e-315
Now playing at  1.646125505e-314
Now playing at  4.823890614e-315
Now playing at  1.1314142064e-314
Now playing at  1.1655019465e-314
Now playing at  5.52737466e-315

The formatted version that is commented out (from the example in README) prints 0.00s, which is expected with the values above.

According to the docs that is supposed to be seconds.
Tried to listen on 'volume' - same result.

Am I missing something obvious here?

Question. Embedding the player in an application

Hello, I have been testing python-mpv for a project. Thank you for creating it!. I would like to create a wxPython (phoenix) widget to encapsulate the play window and be able to display that window as part of a larger application, but have not figured out how to tell python-mpv to open the player inside an existing window rather than on its own window. Is this possible with python-mpv? I am in Linux. Could you post an example on how to pass the window handle? Thank you again.

How can I handle circular buffer overruns when playing back multiple udp streams

I have a program that is playing back multiple udp streams by calling the MPV constructor in a loop. If my loop has enough streams, lets say 8 or more, I will eventually (after a few minutes of playback) get a message from the ffmeg module 'udp - Circular buffer overrun. To avoid, increase fifo_size URL option. To survive in such case, use overrun_nonfatal option' from one of the instances. The video playback hangs after this message is issued and no MPV events are issued. If I wait long enough more instances will do the same thing.

I have increased the fifo_size and set the overrun_nonfatal flag to 1 by concatenating '?fifo_size=1000000&overrun_nonfatal=1' to the udp URL. Unfortunately this only delays the problem and instead of getting a single message, I will get a flood of 'circular buffer overrun' messages.

Assuming I don't add ovverrun_nonfatal=1 to the URL, I would like to just restart any stream that issues the error. Unfortunately it doesn't seem like I can associate the ffmpeg message to a particular MPV instance. I pass a logger function to the MPV constructor that is bound to an instance of a class that identifies the stream, but any messages logged by the ffmpeg component are handled by the instance logger that is passed by the first instantiation of the MPV instance, so I cannot programmatically track down which instance is actually issuing the 'circular buffer overrun' error. It is, of course, obvious when you look at the video playback.

Some details w.r.t my code:

My MPV constructor is called from the constructor of a VideoWindow class and looks something like:

class VideoWindow(ttk.LabelFrame):
def init(self, root_p, url_p, label_p):
ttk.LabelFrame.init(self, root_p)
self.url = url_p
self.label = label_p
self.player = mpv.MPV(log_handler = self.my_log_handler, msg_level='all=warn', ...)
...

def my_log_handler(self, loglevel, component, message):
    logger = logging.getLogger(__name__)
    if loglevel == 'error':
        emit = logger.error
    elif loglevel == 'warn':
        emit = logger.warn
    elif loglevel == 'info':
        emit = logger.info
    elif loglevel == 'fatal':
        emit = logger.fatal
    else:
        emit = logger.debug

    emit('{} [{}] - {}'.format(self.label, component, message))

...

Do you have any advice on how I might achieve my goal of restarting the errant stream?

How to use it in Mac OS?

Hello, I run the example code, but no any responses. The program is running all the time, and there's nothing wrong with it. And this is my code.

player = mpv.MPV(ytdl=True)
url = 'https://www.bilibili.com/video/av16942715/'
player.play(url)

Installing on Windows with Python 3.5

Hello!
Running windows 10 with python 3.5.2

To install I used:
python -m pip install https://github.com/jaseg/python-mpv/zipball/master

import mpv gives the error:

Traceback:
import mpv
backend = CDLL(ctypes.util.find_library('mpv-1.dll'))
self._handle = _dlopen(self._name, mode)

TypeError: bad argument type for built-in operation

Any suggestions?

WinError 193/not a valid Win32 application when loading module on Windows

Here is the backtrace

  File "f:/WORK/PYTHON/webmTest/MPV/webm.py", line 2, in <module>
    import mpv
  File "F:\WORK\PYTHON\WinPython-64bit-3.6.3.0Zero\python-3.6.3.amd64\lib\site-packages\mpv.py", line 31, in <module>
    backend = CDLL('mpv-1.dll')
  File "F:\WORK\PYTHON\WinPython-64bit-3.6.3.0Zero\python-3.6.3.amd64\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)

I have it placed in the directory where the python script is (webm.py)

Raciness in client handle termination leading to hang in Python main thread

I'm not in a position to be certain whether this is a python-mpv issue or a libmpv issue, but I thought it'd be better to have you close it than for you to never know.

This code cases the program to just sit there, doing nothing, while commenting out the af argument makes it work:

#!/usr/bin/env python3

import mpv
player = mpv.MPV(af="lavfi=[acompressor]")

player.play("/srv/fservroot/Videos/LGR Plays - Goat Simulator-j4HY_fxwiZo.mp4")
player.wait_for_playback()

The argument has been copy-pasted, verbatim except for the minor af="..." syntax change, from my .mpv/config where it works without issue.

Properties act on all instances when being applied to a single instance of an MPV class

I am instantiating multiple MPV instances within the the same program, which works. Unfortunately when I set properties for individual instances they are applied to all instances. In particular I have tried to use the volume property and the mute property.

eg.

import mpv

player1 = mpv.MPV()
player2 = mpv.MPV()

player1.loadfile('...')
player2.loadfile('...')

player1.volume = 0

_get_property marked as private

Is there any reason why "_get_property" function is marked as private (underscored)? I need to be able to request player's current playback time without "observing" it, and the only way I can do that now is by:
player._get_property("playback-time")

where it really should be:
player.get_property("playback-time")

Couldn't get examples to run

Hi,

I had no luck getting the examples from the README to run. No exceptions were thrown and no errors were reported. I'm running Python 3.6.1 and MPV 0.25.0.

Regards,
Matt

module 'mpv' has no attribute 'MPV'

Hi,

Enviroment:
Windows 10 x64
Python 3.6
python-mpv 0.3.7
youtube-dl 2017.12.14
mpv 2017.09.13

I'm trying out examples provided in readme.md.
But I get following error:
module 'mpv' has no attribute 'MPV'

I tried playing around and now I get different error when importing mpv module:

Traceback (most recent call last):
  File "C:\Users\Karolis\Desktop\test.py", line 1, in <module>
    import mpv
  File "C:\Users\Karolis\Desktop\mpv.py", line 31, in <module>
    backend = CDLL('mpv-1.dll')
  File "C:\Users\Karolis\AppData\Local\Programs\Python\Python36-32\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found

register_key_binding disables dragging of the VO window

I was in the middle of porting a little helper script from calling mpv as a subprocess to using python-mpv so I could track per-file playback completion without having to re-create the window every time and I ran across an interesting bug.

As soon as I added even a single call to MPV.register_key_binding, the borderless window I was using ceased to be draggable.

I managed to track the problem down to line 975, and applied the following patch to my local copy of mpv.py:

- self.command('enable-section', binding_name)
+ self.command('enable-section', binding_name, 'allow-vo-dragging')

I'd offer a pull request, but I've also made several changes to restore Python 3.4 compatibility and I don't have a quick and easy way to tease apart multiple diff hunks into separate branches and doing it just for that one line doesn't feel worth the effort.

Let python-mpv use mpv.conf / how to change audio device

When I start regular mpv I change the default audio device and disable video:

mpv --audio-device=alsa/plughw:CARD=S51,DEV=0 --no-video ...

I put that into a config file ~/.confg/mpv/mpv.conf which is read by MPV automatically.

How can python-mpv be setup to pick up the mpv config file? Can I pass these configuration values as parameters to the MPV constructor, too?
I tried this so far:

MPV(audio_device='alsa/plughw:CARD=S51,DEV=0')

but in contrast to mpv-cli I cannot get any sound with python-mpv.

Attribute error when registering events

Hello,

consider the following functional code:

import mpv

player = mpv.MPV()
def foo(ev):
    print(ev) 
player.register_event_callback(foo)

This works as expected.

If however, I try to register not a function, but a (class-)method instead, I get an AttributeError:

class Bar:                               
    def baz(self, ev):
        print(ev)
player.register_event_callback(Bar().baz)
~/.local/lib/python3.6/site-packages/mpv.py in register_event_callback(self, callback)
    816         my_handler.unregister_mpv_events()
    817         """
--> 818         callback.unregister_mpv_events = partial(self.unregister_event_callback, callback)
    819         self._event_callbacks.append(callback)
    820 

AttributeError: 'method' object has no attribute 'unregister_mpv_events'

Is there a way of fixing this?

Please add observe_property function

It would be great if this interface would implement the observe_property function. Or is there already something that provides similar functionality?

Can't import mpv with Python 2.7

python-mpv-0.3.6 installed via pip

Traceback (most recent call last):
  File "testmpv.py", line 1, in <module>
    import mpv
  File "/usr/local/lib/python2.7/dist-packages/mpv.py", line 449
    target, *args = devent['event']['args']
            ^
SyntaxError: invalid syntax

use ctypes.util.find_library() to find share lib

share lib of libmpv on Debian is libmpv.so.1, not libmpv.so.
Please use ctypes.util.find_library() to find the library name:

    import ctypes.util
    mpv_libname = ctypes.util.find_library("mpv")
    if not mpv_libname:
        mpv_libname = "libmpv.so"
    backend = CDLL(mpv_libname)

AttributeError when running first "Advanced Usage" example

import mpv

def my_log(loglevel, component, message):
    print('[{}] {}: {}'.format(loglevel, component, message))

player = mpv.MPV(log_handler=my_log, ytdl=True, input_default_bindings=True, input_vo_keyboard=True)

# Property access, these can be changed at runtime
@player.property_observer('time-pos')
def time_observer(_name, value):
    # Here, _value is either None if nothing is playing or a float containing
    # fractional seconds since the beginning of the file.
    print('Now playing at {:.2f}s'.format(value))

player.fullscreen = True
player.loop = 'inf'
# Option access, in general these require the core to reinitialize
player['vo'] = 'opengl'

@player.on_key_press('q')
def my_q_binding():
    print('THERE IS NO ESCAPE')
...
[warn] cplayer: Warning: property 'loop' was replaced with 'loop-playlist' and might be removed in the future.                                                 
Traceback (most recent call last):     
  File "test2.py", line 20, in <module>                                        
    @player.on_key_press('q')          
  File "/home/sean/Development/.virtualenvs/music/lib/python3.6/site-packages/mpv.py", line 1028, in __getattr__                                               
    return self._get_property(_py_to_mpv(name), lazy_decoder)                  
  File "/home/sean/Development/.virtualenvs/music/lib/python3.6/site-packages/mpv.py", line 1011, in _get_property                                             
    cval = _mpv_get_property(self.handle, name.encode('utf-8'), fmt, outptr)   
  File "/home/sean/Development/.virtualenvs/music/lib/python3.6/site-packages/mpv.py", line 104, in raise_for_ec                                               
    raise ex(ec, *args)                
AttributeError: ('mpv property does not exist', -8, (<MpvHandle object at 0x7f963bde5620>, b'on-key-press', 6, <cparam 'P' (0x7f963bdf6808)>)) 

Latest commits, and:

$ python --version
Python 3.6.2
$ uname -a
Linux Caldera 4.12.8-1-ARCH #1 SMP PREEMPT Thu Aug 17 08:37:20 CEST 2017 x86_64 GNU/Linux

Cannot use bound methods with register_key_binding

register_key_binding dies with a somewhat confusing error when you attempt to use a bound method as a handler, as is commonplace in frameworks like PyGTK.

It'd probably be a good idea to document that so less experienced users don't get stuck.

This is the workaround I used:

# pylint: disable=unnecessary-lambda
self.mpv.register_key_binding('q', lambda x, y: self.cb_quit(x, y))

Update PyPI repo

The PyPI repo is quite outdated now, can you please continue uploading this amazing module?

Seriously though, part of the idea of this being all in one handy file is that you can just copy it into your project.

I'm not sure if you recognize your module is quite useful and widely used as it's really is, but please spend some time doing this. It'd be awesome if we can just pip install mpv or, even cooler, if it's possible to use it as a dependency via install_requires=['mpv'] in setup.py's setup. There is even a fork just to upload the updated module (but it's dead now).

Thanks a lot.

v0.3.4 incompatible with mpv v0.14.0 due to _handle_key_binding_message

I get this error:

Traceback (most recent call last): File "/home/jonathon/Documents/Inbox/py-mpv/mpv.py", line 462, in _event_loop message_handlers[target](*args) TypeError: _handle_key_binding_message() missing 1 required positional argument: 'key_name'
When I try to use the 'q' keybinding from the last example in the readme.

"Watch later" does not work

When i can use 'watch-latter' functionality i get the error:

        mpv.MPV(
            ytdl=True,
            vo='vdpau',
            log_handler=print,
            watch_later_directory='~/.config/mpv/watch_later'
        )
   File "/usr/local/lib/python3.5/dist-packages/mpv.py", line 537, in __init__
     _mpv_set_option_string(self.handle, k.replace('_', '-').encode('utf-8'), istr(v).encode('utf-8'))
   File "/usr/local/lib/python3.5/dist-packages/mpv.py", line 102, in raise_for_ec
     raise ex(ec, *args)
 AttributeError: ('mpv option does not exist', -5, (<MpvHandle object at 0x7fb423cd7a60>, b'watch-later-directory', b'~/.config/mpv/watch_later'))

And when i run command player.command('quit-watch-later') without watch-later-directory option nothing happens

loadfile doesn't seem to do anything

import mpv
player = mpv.MPV()
player.loadfile("/home/nivekuil/test.flv")

Nothing happens when I run this - no mpv processes are created, and the program exits immediately. The file plays correctly when I run mpv from the command line.

Tested on Python 3.5.1, mpv 0.15.0, Arch Linux.

lua script not working

Just tried setting script property to a lua script:

player['script'] = "/path/to/test.lua"

It gives me this error:
RuntimeError: ('Generic error getting or setting mpv property', -11, (<MpvHandle object at 0x7f7e33d78a60>, b'options/script', b'/path/to/test.lua'))

It works by running mpv directly: mpv input.mov --script=/path/to/test.lua

The lua script is simply the one from mpv docs:

function on_pause_change(name, value)
    if value == true then
        mp.set_property("fullscreen", "no")
    end
end
mp.observe_property("pause", "bool", on_pause_change)

Inability to handle files over SFTP?

import sys
import os
import subprocess

import mpv


# list of remote paths to songs, prepended with sftp protocol/address
# Example: sftp://[email protected]/home/sean/folder/Hille/craz.mod
with open(os.path.expanduser("~/remote_music.txt")) as f:
    music = [''.join(["sftp://[email protected]", song_path])
             for song_path in f.readlines()]

player = mpv.MPV()
if len(sys.argv) == 1 or sys.argv[1] == "*":
    for song in music:
        player.playlist_append(song)
else:
    pass # add grep/search, curate songs added to playlist

player.playlist_pos = 0
player.wait_for_playback()

With this code, it should create a playlist using a list of remote file paths, then play them after the call to wait. However, the player simply hangs on its call to wait as no song is ever played. Similarly, the following main loop also rapidly prints each song, while not actually playing any of the songs in the list:

player = mpv.MPV()
if len(sys.argv) == 1 or sys.argv[1] == "*":
    for song in music:
        print(song)
        player.play(song)

However, if any of the full remote paths are copy and pasted into normal invocation of mpv, such as:

mpv "sftp://[email protected]/home/sean/folder/Jogeir Liljedahl/overture.mod" --volume=35

plays the song as expected (using the exact same string that was printed to stdout by the program above).

Clarify use of threading in README, please

You should really mention that event handlers are run on a separate thread managed by the library.

My first impression, before my perfectionism drove me to examine your code, was that player.wait_for_playback()was equivalent to something likeQApplication._exec()orgtk.main()` and that event handlers would only run on the main thread and only after that was called.

Stuck in threading on macOS

Hello,

consider the following code:

import mpv

_url = 'test.webm'
mpv = mpv.MPV()
mpv.loadfile(_url)
print('waiting')
mpv.wait_for_playback()
print('done')

On Linux, this will print waiting, then play test.webm, and finally print done as expected.

On macOS 10.12.6 using Python 3.6 and MPV 0.27 however, it only prints waiting and is then stuck forever while the Python-Rocket starts jumping in my Dock.

I looked into python-mpv's code, and for mpv.wait_for_playback() it is stuck in line 557, which is:

self._playback_cond.wait()  # _playback_cond is threading.Condition

Using mpv.wait_for_property('filename', lambda x: x is None) instead, makes it stuck in line 569, which is:

sema.acquire()  # sema is threading.Semaphore

The problem thus seems to somehow be related to the handling of the threading library.
Do you have any suggestion what might be causing this?

This is also possibly a duplicate of #59.

Make ynbool a descriptor object

I hadn't even noticed there were supposed to be properties, but so much the better, thanks :-)

Well, snide remarks aside, these properties are really nifty, especially the read/write ones, and make for much tighter and cleaner code !

The behaviour of the booleans had me scratching my head for a while though, so I thought I'd document it here in case others wondered too...

In interactive mode under ipython:

In [24]: import mpv
In [25]: m=mpv.MPV(pause=True)
In [26]: m.loadfile('test.avi') # video shown paused

as expected:

In [27]: m.pause
Out[27]: True

but...

In [28]: print m.pause
yes

explicit change:

In [29]: m.pause=False # starts playback as expected

and...

In [30]: print m.pause
no

try the classic toggle :

In [31]: m.pause = not m.pause

fail :

In [32]: m.pause
Out[32]: False
In [33]: print m.pause
no

only workaround I've found:

In [34]: m.pause = True if m.pause == 'no' else False
In [35]: m.pause
Out[35]: True
In [36]: print m.pause
yes

Maybe a side effect of running python2 and/or Windows ?

python not launching mpv

I was trying one of your examples but the player never seemed to launch. I tried adding some debugging code as you advised in another issue but i cant seem to figure out why its not launching the player. This is the code im using and the files are just regular h264 files. Im on osx 10.11 and using python 3.6.1 and mpv 0.25.0. The library seems to find the dylib file just fine /usr/local/lib/libmpv.dylib

#!/usr/bin/env python3
import mpv

player = mpv.MPV(log_handler=print)
player.set_loglevel('debug')

player.playlist_append('/Users/christian/Movies/watch/file01.mp4')
player.playlist_append('/Users/christian/Movies/watch/file02.mp4')

player.playlist_pos = 0

while True:
    print(player.playlist)
    player.wait_for_playback()

Log: https://pastebin.com/raw/U5ExvigH

Issue with libmpv.so.1

Just from importing mpv, I'm getting this error:

AttributeError: /usr/lib/arm-linux-gnueabihf/libmpv.so.1: undefined symbol: mpv_create_client

I'm a bit of a noob, so could easily be my fault or the system. Some possibly-relevant details:

  1. On a raspberry pi 3. Manually installed python3.6, which seems to be working fine.
  2. Installed libmpv via "sudo apt-get install libmpv-dev".
  3. Installed mpv. Command "mpv myfile.mp3" works fine.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.