diff --git a/.github/workflows/pub_docs.yml b/.github/workflows/pub_docs.yml index daaf6a23..2b7e0ead 100644 --- a/.github/workflows/pub_docs.yml +++ b/.github/workflows/pub_docs.yml @@ -8,17 +8,29 @@ on: jobs: publish-docs: name: Build sphinx documentation on docs branch - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest if: | ${{ github.event_name=='workflow_dispatch' || (github.event_name=='push' && (startsWith(github.ref, 'refs/tags') || startsWith(github.event.head_commit.message, 'docs ')))}} steps: - - name: Set up FFmpeg - uses: FedericoCarboni/setup-ffmpeg@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} + # - name: Set up FFmpeg + # uses: FedericoCarboni/setup-ffmpeg@v3 + # with: + # # A specific version to download, may also be "release" or a specific version + # # like "6.1.0". At the moment semver specifiers (i.e. >=6.1.0) are supported + # # only on Windows, on other platforms they are allowed but version is matched + # # exactly regardless. + # ffmpeg-version: release + # # Target architecture of the ffmpeg executable to install. Defaults to the + # # system architecture. Only x64 and arm64 are supported (arm64 only on Linux). + # architecture: 'x64' + # # As of version 3 of this action, builds are no longer downloaded from GitHub + # # except on Windows: https://github.com/GyanD/codexffmpeg/releases. + # github-token: ${{ github.server_url == 'https://github.com' && github.token || '' }} + - name: Setup FFmpeg + uses: AnimMouse/setup-ffmpeg@v1 - name: Checkout uses: actions/checkout@master diff --git a/.github/workflows/test_n_pub.yml b/.github/workflows/test_n_pub.yml index 83b6fb39..b80bab55 100644 --- a/.github/workflows/test_n_pub.yml +++ b/.github/workflows/test_n_pub.yml @@ -15,19 +15,11 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, "3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] os: [ubuntu-latest, macos-latest, windows-latest] # python-version: [3.7, 3.8, 3.9] # os: [windows-latest] exclude: - - os: macos-latest - python-version: 3.8 - - os: windows-latest - python-version: 3.8 - - os: macos-latest - python-version: 3.9 - - os: windows-latest - python-version: 3.9 - os: macos-latest python-version: 3.10 - os: windows-latest @@ -36,20 +28,40 @@ jobs: python-version: 3.11 - os: windows-latest python-version: 3.11 + - os: macos-latest + python-version: 3.12 + - os: windows-latest + python-version: 3.12 + - os: macos-latest + python-version: 3.13 + - os: windows-latest + python-version: 3.13 steps: - run: echo ${{github.ref}} - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - - name: Set up FFmpeg - uses: FedericoCarboni/setup-ffmpeg@v3 - with: - architecture: x64 - github-token: ${{ secrets.GITHUB_TOKEN }} + # - name: Set up FFmpeg + # uses: FedericoCarboni/setup-ffmpeg@v3 + # with: + # # A specific version to download, may also be "release" or a specific version + # # like "6.1.0". At the moment semver specifiers (i.e. >=6.1.0) are supported + # # only on Windows, on other platforms they are allowed but version is matched + # # exactly regardless. + # ffmpeg-version: release + # # Target architecture of the ffmpeg executable to install. Defaults to the + # # system architecture. Only x64 and arm64 are supported (arm64 only on Linux). + # architecture: 'x64' + # # As of version 3 of this action, builds are no longer downloaded from GitHub + # # except on Windows: https://github.com/GyanD/codexffmpeg/releases. + # github-token: ${{ github.server_url == 'https://github.com' && github.token || '' }} + + - name: Setup FFmpeg + uses: AnimMouse/setup-ffmpeg@v1 - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.arch }} @@ -57,10 +69,9 @@ jobs: - name: Setup Python dependencies run: | python -m pip install -U pip - pip install -U build pytest pytest-github-actions-annotate-failures - - - name: Install ffmpegio package - run: pip install -q . + pip install . + pip install -r tests/requirements.txt + pip install -U build pytest-github-actions-annotate-failures - name: Run tests run: pytest -vv @@ -75,10 +86,10 @@ jobs: steps: - run: echo ${{github.ref}} - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.arch }} @@ -96,13 +107,14 @@ jobs: distribute: name: Distribution runs-on: ubuntu-latest + permissions: write-all needs: [tests, test_no_ffmpeg] if: startsWith(github.ref, 'refs/tags') steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: "3.x" # Version range or exact version of a Python version to use, using SemVer's version range syntax @@ -115,7 +127,7 @@ jobs: run: python -m build --sdist --wheel --outdir dist/ . - name: add python distribution files to release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: files: dist/* env: @@ -127,8 +139,7 @@ jobs: # password: ${{ secrets.TEST_PYPI_API_TOKEN }} # repository_url: https://test.pypi.org/legacy/ # skip_existing: true - - name: Publish distribution 📦 to PyPI uses: pypa/gh-action-pypi-publish@release/v1 - with: - password: ${{ secrets.PYPI_API_TOKEN }} + # with: + # password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c81a248..357aeb84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,91 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] +## [0.12.0] - 2026-05-25 + +### Added + +- `plugins.rawdata_pillow` - added pillow plugin to convert video/image stream to/from Pillow Image object + +### Changed + +- `caps` to cache the outputs of its functions + +### Fixed + +- FFmpeg v8 and v8.1 compatibility +- FFmpeg version may start with 'n' to support a version name with a release branch name +- `caps` subpackage - fixed several bugs +- `plugins.finder_ffdl` - fixed logic to check existence of ffmpeg binaries + +## [0.11.1] - 2025-05-17 + +### Fixed + +- `audio.filter()` and `image.filter()`: fixed to process their `sp_kwargs` argument +- numPy plugin: fixed to convert the array view to bytes (fixes `stdin` operations in Linux) +- `probe`: fixed to accept any stringifiable object as url also cleaned up the url processing + +## [0.11.0] - 2024-12-22 + +### Changed + +- allow writers' `extra_inputs` arguments to be `str` or `tuple[str, dict|None]` +- `probe` functions accepts PathLike object as the media url + +### Added + +- `configure.add_urls()` to handle `extra_inputs` argument processing + +### Fixed + +- `probe._exec()` to decode the error message sent from ffprobe +- `filtergraph.Filter.add_labels()`: fixed a syntax error + +## [0.10.0] - 2024-07-03 + +### Changed + +- `caps` submodule - update format regex for v7 compatibility +- `filter` functions accept `expr=None` for implicit filters (e.g., reshape and resample) +- `probe.video/audio_stream_basic()`: added keep_str_values bool arg +- `probe._items_to_numeric()`: not convert hex values +- `probe`: added custom audio & video info probe functions - added `_audio_info()` and `_video_info()` +- `audio.read()` & `SimpleAudioReader`: switched to use `_audio_info()` +- `image.read()` `video.read()`, & `SimpleVideoReader`: switched to use `_video_info()` +- `probe`: `url` argument to support bytes-like object +- `probe._items_to_numeric()`: added to convert hex int and a:b ratio fraction +- `probe:_add_select_streams`: convert stream spec to str (if int) +- `probe`: added `keep_str_values` argument to ffprobe calling functions +- `probe`: added `keep_optional_fields` argument to ffprobe calling functions +- `probe`: added `sp_kwargs` argument to all ffprobe running functions +- `probe`: added `frames()` to `__all__` +- `open()`: major changes in input arguments +- `Filter` classes: Renamed constructor arguments +- `LoggerThread`: pass ffmpeg logs to debug log +- `open()`: no longer a context manager +- `Popen.send_signal`: defaults to perform ctrl-c +- `SimpleReaderBase.close`: poll before calling terminate + +### Fixed + +- `AviMediaReader`: fixed Issue #46 - a bug in `AviReaderThread.wait` +- `AviMediaReader`: fixed `__next__` behavior (now throws `StopIteration`) +- `AviReaderThread`: fixed buffer concatenation bug +- `compose_filter_args`: fixed escaping commas +- `probe._resolve_entries()`: fixed return value +- `probe.query`: fixed stream request id +- `probe`: fixed`cache_output=True` operation +- `probe.query()`: fixed a logic to return a single stream +- `probe:_add_show_entries`: fixed error if entries is bool +- `Popen`: fixed `progmon`'s cancel operation (ctrl-c) +- `ProgressMonitorThread`: call cancelfun() only once + +### Removed + +- `probe`: removed auto-caching ffprobe output +- + ## [0.9.1] - 2024-02-19 ### Fixed @@ -388,7 +473,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a - Main functionality of `transcode`, `video`, `audio`, `image`, `SimpleStreams`, `probe`, and `caps` modules. - Preliminary implementations of `FilterGraph` and `FFmpegError` classes. -[unreleased]: https://github.com/python-ffmpegio/python-ffmpegio/compare/v0.9.1...HEAD +[unreleased]: https://github.com/python-ffmpegio/python-ffmpegio/compare/v0.12.0...HEAD +[0.12.0]: https://github.com/python-ffmpegio/python-ffmpegio/compare/v0.11.1...v0.12.0 +[0.11.1]: https://github.com/python-ffmpegio/python-ffmpegio/compare/v0.11.0...v0.11.1 +[0.11.0]: https://github.com/python-ffmpegio/python-ffmpegio/compare/v0.10.0...v0.11.0 +[0.10.0]: https://github.com/python-ffmpegio/python-ffmpegio/compare/v0.9.1...v0.10.0 [0.9.1]: https://github.com/python-ffmpegio/python-ffmpegio/compare/v0.9.0...v0.9.1 [0.9.0]: https://github.com/python-ffmpegio/python-ffmpegio/compare/v0.8.6...v0.9.0 [0.8.6]: https://github.com/python-ffmpegio/python-ffmpegio/compare/v0.8.5...v0.8.6 diff --git a/README.rst b/README.rst index fd2828c7..07996e70 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -`ffmpegio-core`: Media I/O with FFmpeg in Python +`ffmpegio`: Media I/O with FFmpeg in Python =================================================== |pypi| |pypi-status| |pypi-pyvers| |github-license| |github-status| @@ -11,47 +11,69 @@ :alt: PyPI - Python Version .. |github-license| image:: https://img.shields.io/github/license/python-ffmpegio/python-ffmpegio :alt: GitHub License -.. |github-status| image:: https://img.shields.io/github/workflow/status/python-ffmpegio/python-ffmpegio/Run%20Tests +.. |github-status| image:: https://img.shields.io/github/actions/workflow/status/python-ffmpegio/python-ffmpegio/test_n_pub.yml?branch=main :alt: GitHub Workflow Status Python `ffmpegio` package aims to bring the full capability of `FFmpeg `__ to read, write, probe, and manipulate multimedia data to Python. FFmpeg is an open-source cross-platform multimedia framework, which can handle most of the multimedia formats available today. -.. note:: - - Since v0.3.0, `ffmpegio` Python distribution package has been split into `ffmpegio-core` and `ffmpegio` to allow - Numpy-independent installation. - -Install the full `ffmpegio` package via ``pip``: - -.. code-block:: bash - - pip install ffmpegio - -If `numpy.ndarray` data I/O is not needed, instead use - -.. code-block:: bash - - pip install ffmpegio-core - Main Features ------------- * Pure-Python light-weight package interacting with FFmpeg executable found in - the system -* Transcode a media file to another in Python + your system * Read, write, filter, and create functions for audio, image, and video data * Context-managing `ffmpegio.open` to perform stream read/write operations of video and audio -* Automatically detect and convert audio & video formats to and from `numpy.ndarray` properties +* Media readers can output the data in a Numpy array (if Numpy is installed) or a plain :code:`bytes` + objects in a :code:`dict`. The mode of operation can be switched with :code:`ffmpegio.use` function. +* Media writers can write a new media file from either data given in a Numpy array or :code:`bytes` + objects in a :code:`dict`. +* Write Matplotlib figures to images or to a video (a simpler interface than Matplotlib's Animation writers). +* Read video data as a list of Pillow :code:`Image`s and write Pillow :code:`Image`s to a video stream. * Probe media file information * Accepts all FFmpeg options including filter graphs +* Transcode a media file to another in Python * Supports a user callback whenever FFmpeg updates its progress information file (see `-progress` FFmpeg option) * `ffconcat` scripter to make the use of `-f concat` demuxer easier * I/O device enumeration to eliminate the need to look up device names. (currently supports only: Windows DirectShow) * More features to follow +Installation +------------ + +Install the full `ffmpegio` package via ``pip``: + +.. code-block:: bash + + pip install ffmpegio + +Following optional external packages are required to enable the :code:`ffmpegio` features that interact +with them. + +.. table:: + :class: tight-table + + ========================== ========================================================================== ===================================== + Distro package name :code:`ffmpegio` features Deprecated plugin names + ========================== ========================================================================== ===================================== + :code:`numpy` Support Numpy array inputs and outputs instead of bytes :code:`ffmpegio` + :code:`matplotlib` Support generation of images or videos from Matplotlib figure :code:`ffmpegio-plugin-mpl` + :code:`pillow` Support :code:`PIL.Image.Image` as the input and output video frames + :code:`ffmepeg-downloader` Support the FFmpeg binaries installed by the :code:`ffdl install` command :code:`ffmpegio-plugin-downloader` + :code:`static-ffmpeg` Support the FFmpeg binaries installed by :code:`static-ffmpeg` :code:`ffmpegio-plugin-static-ffmpeg` + ========================== ========================================================================== ===================================== + +These features are automatically enabled if the external packages are installed along along side with `ffmpegio`. +:code:`ffmpegio` is imported + +.. note:: + + Prior to v0.11.0, these features were only enabled via installing separate plugin packages (listed in the table above). + :code:`ffmpegio` v0.11 and :code:`ffmpegio-core` v0.11 are identical, and :code:`ffmpegio-core` will no longer receive + the updates. For the version upgrade instruction, please read `this Wiki entry `__` + Documentation ------------- @@ -74,6 +96,8 @@ To import `ffmpegio` - `Write Audio, Image, & Video Files `_ - `Filter Audio, Image, & Video Data `_ - `Stream I/O `_ +- `Video from Matplotlib Figure