ozmartian / vidcutter

A modern yet simple multi-platform video cutter and joiner.
GNU General Public License v3.0
1.81k stars 135 forks source link

VidCutter 3.0.0 AppImage cannot find libmpv in the usual places #12

Closed probonopd closed 7 years ago

probonopd commented 7 years ago

Python fails to import mpv.

me@host:~$ '/home/me/Downloads/VidCutter-3.0.0-linux-x64.AppImage' 
Traceback (most recent call last):
  File "/tmp/.mount_jgstZG/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main
    "__main__", mod_spec)
  File "/tmp/.mount_jgstZG/usr/lib/python3.5/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/tmp/.mount_jgstZG/usr/lib/python3/dist-packages/vidcutter/__main__.py", line 37, in <module>
    from vidcutter.videocutter import VideoCutter
  File "/tmp/.mount_jgstZG/usr/lib/python3/dist-packages/vidcutter/videocutter.py", line 40, in <module>
    import vidcutter.mpv as mpv
  File "/tmp/.mount_jgstZG/usr/lib/python3/dist-packages/vidcutter/mpv.py", line 29, in <module>
    raise OSError("Cannot find libmpv in the usual places.")
OSError: Cannot find libmpv in the usual places.

This is the offending code: https://github.com/ozmartian/vidcutter/blob/7ca6960638633958387bb7034cbabdd5dd9e25e9/vidcutter/mpv.py#L27

According to https://docs.python.org/3/library/ctypes.html

On Linux, find_library() tries to run external programs (/sbin/ldconfig, gcc, objdump and ld) to find the library file. It returns the filename of the library file.

Changed in version 3.6: On Linux, the value of the environment variable LD_LIBRARY_PATH is used when searching for libraries, if a library cannot be found by any other means.

Since your AppImage bundles 3.5, it ignores LD_LIBRARY_PATH. So this falls down for relocatable bundles like AppImages.

Can you change the Python code to load the library using a path relative to the file loading it?

ozmartian commented 7 years ago

@probonopd thanks for the message matey...

i didn't have the time to get trusty installed so the first AppImage was a rushed one built on xenial but I have since gotten a trusty VM setup and all issues should now be resolved... you can test again using the latest AppImage on the releases page..

FYI, the error you quoted may be something you might want to look into re your AppImage framework/tools incase it helps others... basically, VidCutter is using libmpv via python ctypes now and the usual way that many wrapper libraries search for system libraries is via ctypes own function which on normal systems returns the .so filename. so in the case of VidCutter, for example:

import ctypes.util
sofile = ctypes.util.find_library('mpv')

the value of sofile should return as libmpv.so.1 but within the AppDir folder structure, and thus the resulting AppImage, this wouldn't work, returning None. seems the ctypes function is directly looking outside the AppImage and into the actual system libraries.

I worked around it with a simple exception clause hardcoding the lib's filename which i didn't expect to work but it works just fine. so it seems python ctypes find function isn't AppImag friendly but if the library filename is known, as is the case here, it works fine when actualling using it during execution.

I also had to bring in a lot of third party libs to my PPA for trusty alone because libmpv isn't available until vivid, just the mpv app itself but thats no concern of yours, just wanted to share and explain the full case here and that once all dependencies were satisfied and the above fix applied, its working real nicely.

I did all my testing from a trusty live CD so it had 0 additional packages installed. Let me know that its working and tests out fine for you :-)

Thanks!

ozmartian commented 7 years ago

@probonopd

for your reference, incase i wasn't clear enough re my ctypes workaround. the simple fixed code looks like this:

sofile = ctypes.util.find_library('mpv')
if sofile is None:
    sofile = 'libmpv.so.1'

any python based application or module using C extensions would come across this issue as that ctypes function is the documented recommended way of identifying system libs.

not sure if you're flunt in python so to help out, you can test in a AppDir with code like :

from ctypes.util import find_library
print(find_library('ssl'))
print(find_library('png'))
print(find_library('pthread'))

then substitute the library names for libraries only available in the AppDir and not the base host system.

give me a shout if you want any help with this if you decide to take a look (if its important enough i mean). am happy to help out anyway i can...

ozmartian commented 7 years ago

closing in order to manage open issues list but please continue correspondence via this thread

probonopd commented 7 years ago

Added to https://github.com/probonopd/AppImageKit/wiki/Bundling-Python-apps. Thanks @ozmartian. Works now.