Giter Site home page Giter Site logo

static_ffmpeg's Introduction

Actions Status Actions Status Actions Status

static-ffmpeg

The easiest way to get ffmpeg v5 installed through python.

Install

> pip install static-ffmpeg

Usage

import static_ffmpeg
# ffmpeg installed on first call to add_paths(), threadsafe.
static_ffmpeg.add_paths()  # blocks until files are downloaded
# or static_ffmpeg.add_paths(weak=True) to only add if ffmpeg/ffprobe not already on path
# Now ffmpeg and ffprobe will use static_ffmpeg versions.
os.system("ffmpeg -i myfile.mp4 ...")

Or if you want more lazy behavior to install on first use, or you don't want to modify system paths, use static_ffmpeg

import static_ffmpeg
# ffmpeg installed on first call, threadsafe.
os.system("static_ffmpeg -i myfile.mp4 ...")

You can also use it on the command line

> pip install static-ffmpeg
> static_ffmpeg -i file.mp4 ...
> static_ffprobe ...
> static_ffmpeg_paths
FFMPEG=c:\users\niteris\dev\static_ffmpeg\static_ffmpeg\bin\win32\ffmpeg.exe
FFPROBE=c:\users\niteris\dev\static_ffmpeg\static_ffmpeg\bin\win32\ffprobe.exe

About

This tool installs binaries for ffmpeg and ffprobe binary (with all plugins and codecs) into the running platform. The platform binaries are installed on first use and is done without requiring elevated permissions.

This package is designed to allow tools that rely on ffmpeg to have a fully featured ffmpeg available by just including this package. No seperate install of ffmpeg is needed.

Without this library...

Your ffmpeg tool would have to rely on the user to install ffmpeg, with the right build settings to ensure your tool functions correctly. This is a major pain for ffmpeg based tools (missing codecs for example) and this library solves this problem.

As of now, binaries are available for:

  • win32 (Windows)
  • darwin (MacOS)
  • linux (From Ubuntu 20LTS)
  • Pull requests to support for other platforms are welcome! Too add support please see related git repo: ffmpeg_bins.

There is both an python api and a command line api. After installing this package the command line aliases will be available:

  • static_ffmpeg operates just like ffmpeg
  • static_ffprobe operates just like ffprobe.
  • static_ffmpeg_paths prints out the paths of the ffmpeg binaries.
> static_ffmpeg_paths
FFMPEG=c:\users\niteris\dev\static_ffmpeg\static_ffmpeg\bin\win32\ffmpeg.exe
FFPROBE=c:\users\niteris\dev\static_ffmpeg\static_ffmpeg\bin\win32\ffprobe.exe

Api

Here's how to get the binaries and execute them.

# Using the alias method
import os
# Platform binaries will be installed the first run.
os.system("static_ffmpeg -version")  # static_ffmpeg is an alias for this tools ffmpeg.
os.system("static_ffprobe -version")
# Using the program location method
import subprocess
from static_ffmpeg import run
# Platform binaries are installed on the first run of below.
ffmpeg, ffprobe = run.get_or_fetch_platform_executables_else_raise()
# ffmpeg, ffprobe will be paths to ffmpeg and ffprobe.
subprocess.check_output([ffmpeg, "-version"])
subprocess.check_output([ffprobe, "-version"])

Testing

  • Clone this project git clone https://github.com/zackees/static_ffmpeg
  • cd static_ffmpeg
  • Then run tox tox

Virtual Environment (optional)

To test it in a virtual environment, use this easy helper:

To easily setup a virtual environment, please run

python setupvirtualenv.py

Then run ./activate.sh to activate the shell.

Binary source

Version

ffmpeg and ffprobe are both version: 5.0

Release History

  • 2.6: Bugfix, add_paths(...) can now be called multiple times without polluting the os env path.
  • 2.5: add_paths() now has optional weak parameter (default False). If True then ffmpeg/ffprobe binaries are only only if either ffmpeg OR ffprobe doesn't already exist on path
  • 2.3: Adds static_ffmpeg.add_paths()
  • 2.2: Addressed bug 9 in some cases static_ffmpeg couldn't handle spaces in mp4 names.
  • 2.1: Addressed bug 7 on Win32 for not handling spaces in directory names in the site packages path.
  • 2.0:
    • ffmpeg upgraded to 5.0
    • added ffprobe (static_ffprobe or get run.get_platform_executables_or_raise() to get the binary location)
    • Now downloads platform specific binary to reduce install size (reduced 2/3rds of the install size vs 1.0)
  • 1.0:
    • ffmpeg 4.4 released + tests

static_ffmpeg's People

Contributors

matthiasmiller avatar zackees 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

Watchers

 avatar  avatar

static_ffmpeg's Issues

platform specific ffmpeg

I love what this package hopes to achieve, installation of ffmpeg in general is a hustle especially on linux where there are so many versions depending on where on got it. I think you should create another repo for linux-ffmpeg which is would be lighter, but would remove the hustle of checking if ffmpeg is installed on the device before running or whether it's installed on path and other issues.

static_ffmpeg fails to see video file where ffmpeg doesnt

I'm making a subprocess call like so:

subprocess.call([
                'static_ffmpeg',                   # call ffmpeg
                '-ss', str(start_time),          # our clip starts here
                '-i', infile_video,         # this is the video to be converted
                '-t', str(end_time - start_time), #how long our clip is
                '-threads', '4',            # use 4 threads for the video conversion
                '-c:v', 'libvpx-vp9',       # c[odec]:v[ideo] - we use libvpx cause we want webm
                '-c:a', 'libvorbis',        # c[odec]:a[udio] - this is the one everyone else was using
                '-b:v',  '400k',            # reccomended video bitrate
                '-b:a', '192k',             # reccomended audio bitrate
                '-deadline', 'good',    # setting for quality vs. speed (best, good, realtime (fastest)); boundry for quality vs. time set the following settings
                '-qmin', '0',               # quality minimum boundry. (lower means better)
                '-qmax', '50',              # quality maximum boundry (higher means worse)
                uniquename               # file to be written out
            ])

When I do, I get this error Some: No such file or directory. Meanwhile, this works fine:

subprocess.call([
                'ffmpeg',                   # call ffmpeg
                '-ss', str(start_time),          # our clip starts here
                '-i', infile_video,         # this is the video to be converted
                '-t', str(end_time - start_time), #how long our clip is
                '-threads', '4',            # use 4 threads for the video conversion
                '-c:v', 'libvpx-vp9',       # c[odec]:v[ideo] - we use libvpx cause we want webm
                '-c:a', 'libvorbis',        # c[odec]:a[udio] - this is the one everyone else was using
                '-b:v',  '400k',            # reccomended video bitrate
                '-b:a', '192k',             # reccomended audio bitrate
                '-deadline', 'good',    # setting for quality vs. speed (best, good, realtime (fastest)); boundry for quality vs. time set the following settings
                '-qmin', '0',               # quality minimum boundry. (lower means better)
                '-qmax', '50',              # quality maximum boundry (higher means worse)
                uniquename               # file to be written out
            ])

If it's relevant, the media files are in script's directory, and they end up having filenames with whitespace so their names look like: 'Some Youtube Video.mp4'

This the package is pointless no offence

Yes FFMPEG is a binary package, Python is a scripting language... How is your package on PyPI? This does nothing. FFMPEG has separate binaries for each platform like the python (binary) interpreter is different on every platform. please explain why is super important?

add_path with weak=True will always return False

Hi,

I just discovered this tool and I started using it on my project, but I couldn't get it to work in the first place.
I wanted to install ffmpeg, but only if it wasn't, so I set the weak flag to True. The result I got from the add_paths method was always False.

By looking up in the code, I understood why.
This part in the code is responsible for this behaviour :

    if weak:
        has_ffmpeg = _has("ffmpeg") is not None
        has_ffprobe = _has("ffprobe") is not None
        if has_ffmpeg and has_ffprobe:
            return False

_has returns a boolean value, but is compared to None. This will always return True !

>>> True is not None # True
>>> False is not None # True

Thus, the method will always return False, even though ffmpeg isn't installed !

Got errors on first call

Sorry to interrupt, I'm using win64 platform and I got several errors while executing the 'static_ffmpeg -i file.mp4 ...' command for first call.

Traceback (most recent call last):
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\urllib3\connection.py", line 174, in _new_conn
    conn = connection.create_connection(
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\urllib3\util\connection.py", line 72, in create_connection
    for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\socket.py", line 955, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 11004] getaddrinfo failed

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\urllib3\connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\urllib3\connectionpool.py", line 386, in _make_request
    self._validate_conn(conn)
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\urllib3\connectionpool.py", line 1042, in _validate_conn
    conn.connect()
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\urllib3\connection.py", line 358, in connect
    self.sock = conn = self._new_conn()
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\urllib3\connection.py", line 186, in _new_conn
    raise NewConnectionError(
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPSConnection object at 0x0000016F50747A60>: Failed to establish a new connection: [Errno 11004] getaddrinfo failed

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\requests\adapters.py", line 489, in send
    resp = conn.urlopen(
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\urllib3\connectionpool.py", line 787, in urlopen
    retries = retries.increment(
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\urllib3\util\retry.py", line 592, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /zackees/ffmpeg_bins/main/v5.0/win32.zip (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x0000016F50747A60>: Failed to establish a new connection: [Errno 11004] getaddrinfo failed'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "D:\Projekt\AI\Anaconda3\envs\My_Env\Scripts\static_ffmpeg.exe\__main__.py", line 7, in <module>
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\static_ffmpeg\run.py", line 125, in main_static_ffmpeg
    ffmpeg_exe, _ = get_or_fetch_platform_executables_else_raise()
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\static_ffmpeg\run.py", line 69, in get_or_fetch_platform_executables_else_raise
    return _get_or_fetch_platform_executables_else_raise_no_lock(
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\static_ffmpeg\run.py", line 93, in _get_or_fetch_platform_executables_else_raise_no_lock
    download_file(url, local_zip)
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\static_ffmpeg\run.py", line 51, in download_file
    with requests.get(url, stream=True) as req:
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\requests\api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\requests\api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\requests\sessions.py", line 587, in request
    resp = self.send(prep, **send_kwargs)
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\requests\sessions.py", line 723, in send
    history = [resp for resp in gen]
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\requests\sessions.py", line 723, in <listcomp>
    history = [resp for resp in gen]
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\requests\sessions.py", line 266, in resolve_redirects
    resp = self.send(
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\requests\sessions.py", line 701, in send
    r = adapter.send(request, **kwargs)
  File "d:\Projekt\AI\Anaconda3\envs\My_Env\lib\site-packages\requests\adapters.py", line 565, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /zackees/ffmpeg_bins/main/v5.0/win32.zip (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x0000016F50747A60>: Failed to establish a new connection: [Errno 11004] getaddrinfo failed'))

I've checked my network and it's working fine. Any solutions?

Consider to use sys.stderr instead of sys.stdout when frozen

Can you use stderr when frozen instead of stdout, sometimes frozen application don't have access to stdout because they don't have any console which is gonna make the download fail because this library print directly into stdout and stdout is None

You can change it or simply add this:

if getattr(sys, "frozen", False):
    sys.stdout = sys.stderr

Because of this, to get around this problem in my project i did a little patching:

# modify static_ffmpeg add_paths
def add_ffmpeg_to_path(weak=False) -> bool:
    """Add the ffmpeg executable to the path"""
    if getattr(sys, "frozen", False):
        # pylint: disable=import-outside-toplevel, protected-access
        from static_ffmpeg import _add_paths, run
        run.sys.stdout = sys.stderr
        if weak:
            has_ffmpeg = _add_paths._has("ffmpeg") is not None
            has_ffprobe = _add_paths._has("ffprobe") is not None
            if has_ffmpeg and has_ffprobe:
                return False
        ffmpeg, _ = run.get_or_fetch_platform_executables_else_raise()
        os.environ["PATH"] = os.pathsep.join([os.path.dirname(ffmpeg), os.environ["PATH"]])
        return True
    else:
        # pylint: disable=import-outside-toplevel
        from static_ffmpeg import _add_paths
        return _add_paths.add_paths()

Thank you ๐Ÿ™

Add +r so user can read the binary

The binary could do with sudo chmod u+r because the inability to read the file breaks some common things - e.g. my daily backup process throws an error because it can't read the binary.

feature req: adding ffmpeg path to system path when module is imported

Hey,

I'm developing an FFmpeg-wrapper package called ffmpegio (please check it out if you have a chance) and have been looking for a user-friendly way of getting the ffmpeg to their system, and I think what you got here does exactly what I need but need another step.

I'm proposing to make your package to add the ffmpeg directory to system path when import static_ffmpeg takes place. This lets users to sys-call ffmpeg, making your package useful for users who uses various FFmpeg wrappers not just mine. What do you think?

I've tested the idea on my fork and it does work. If you like the idea, I'd be happy to PR my mods.

Thanks,
Kesh

P.S., (perhaps I should raise another issue but) could you also include ffprobe? They kinda go hand-in-hand.

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.