Metadata-Version: 2.1
Name: ffmpegio-core
Version: 0.4.1
Summary: Media I/O with FFmpeg
Home-page: https://python-ffmpegio.github.io/python-ffmpegio
License: GPL-2.0 License
Project-URL: Repository, https://github.com/python-ffmpegio/python-ffmpegio
Project-URL: Discussions, https://github.com/python-ffmpegio/python-ffmpegio/discussions
Project-URL: Issues, https://github.com/python-ffmpegio/python-ffmpegio/issues
Project-URL: Pull Requests, https://github.com/python-ffmpegio/python-ffmpegio/pulls
Keywords: multimedia,ffmpeg
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
Classifier: Topic :: Multimedia :: Sound/Audio
Classifier: Topic :: Multimedia :: Sound/Audio :: Capture/Recording
Classifier: Topic :: Multimedia :: Sound/Audio :: Conversion
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Multimedia :: Video :: Capture
Classifier: Topic :: Multimedia :: Video :: Conversion
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Requires-Python: >=3.7
Description-Content-Type: text/x-rst
License-File: LICENSE

`ffmpegio-core`: Media I/O with FFmpeg in Python
===================================================

|pypi| |pypi-status| |pypi-pyvers| |github-license| |github-status|

.. |pypi| image:: https://img.shields.io/pypi/v/ffmpegio
  :alt: PyPI
.. |pypi-status| image:: https://img.shields.io/pypi/status/ffmpegio
  :alt: PyPI - Status
.. |pypi-pyvers| image:: https://img.shields.io/pypi/pyversions/ffmpegio
  :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
  :alt: GitHub Workflow Status

Python `ffmpegio` package aims to bring the full capability of `FFmpeg <https://ffmpeg.org>`__
to read, write, 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.

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
* 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
* Probe media file information
* Accepts all FFmpeg options including filter graphs
* Supports a user callback whenever FFmpeg updates its progress information file 
  (see `-progress` FFmpeg option)
* Advanced users can gain finer controls of FFmpeg I/O with `ffmpegio.ffmpegprocess` submodule
* More features to follow

Documentation
-------------

Visit our `GitHub page here <https://python-ffmpegio.github.io/python-ffmpegio/>`__

Examples
--------

To import `ffmpegio`

.. code-block:: python

  >>> import ffmpegio

Transcoding
^^^^^^^^^^^

.. code-block:: python

  >>> # transcode, overwrite output file if exists, showing the FFmpeg log
  >>> ffmpegio.transcode('input.avi', 'output.mp4', overwrite=True, show_log=True) 

  >>> # 1-pass H.264 transcoding
  >>> ffmpegio.transcode('input.avi', 'output.mkv', vcodec='libx264', show_log=True,
  >>>                    preset='slow', crf=22, acodec='copy') 

  >>> # 2-pass H.264 transcoding
  >>> ffmpegio.transcode('input.avi', 'output.mkv', two_pass=True, show_log=True,
  >>>                    **{'c:v':'libx264', 'b:v':'2600k', 'c:a':'aac', 'b:a':'128k'}) 

Read Audio Files
^^^^^^^^^^^^^^^^

.. code-block:: python

  >>> # read audio samples in its native sample format and return all channels
  >>> fs, x = ffmpegio.audio.read('myaudio.wav') 
  >>> # fs: sampling rate in samples/second, x: [nsamples x nchannels] numpy array

  >>> # read audio samples from 24.15 seconds to 63.2 seconds, pre-convert to mono in float data type 
  >>> fs, x = ffmpegio.audio.read('myaudio.flac', ss=24.15, to=63.2, sample_fmt='dbl', ac=1)

  >>> # read filtered audio samples first 10 seconds
  >>> #   filter: equalizer which attenuate 10 dB at 1 kHz with a bandwidth of 200 Hz 
  >>> fs, x = ffmpegio.audio.read('myaudio.mp3', t=10.0, af='equalizer=f=1000:t=h:width=200:g=-10')

Read Image Files / Capture Video Frames
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: python

  >>> # list supported image extensions
  >>> ffmpegio.caps.muxer_info('image2')['extensions']
  ['bmp', 'dpx', 'exr', 'jls', 'jpeg', 'jpg', 'ljpg', 'pam', 'pbm', 'pcx', 'pfm', 'pgm', 'pgmyuv', 
   'png', 'ppm', 'sgi', 'tga', 'tif', 'tiff', 'jp2', 'j2c', 'j2k', 'xwd', 'sun', 'ras', 'rs', 'im1', 
   'im8', 'im24', 'sunras', 'xbm', 'xface', 'pix', 'y']

  >>> # read BMP image with auto-detected pixel format (rgb24, gray, rgba, or ya8)
  >>> I = ffmpegio.image.read('myimage.bmp') # I: [height x width x ncomp] numpy array

  >>> # read JPEG image, then convert to grayscale and proportionally scale so the width is 480 pixels
  >>> I = ffmpegio.image.read('myimage.jpg', pix_fmt='grayscale', s='480x-1')

  >>> # read PNG image with transparency, convert it to plain RGB by filling transparent pixels orange
  >>> I = ffmpegio.image.read('myimage.png', pix_fmt='rgb24', fill_color='orange')

  >>> # capture video frame at timestamp=4:25.3 and convert non-square pixels to square
  >>> I = ffmpegio.image.read('myvideo.mpg', ss='4:25.3', square_pixels='upscale')

  >>> # capture 5 video frames and tile them on 3x2 grid with 7px between them, and 2px of initial margin
  >>> I = ffmpegio.image.read('myvideo.mp4', vf='tile=3x2:nb_frames=5:padding=7:margin=2')

  >>> # create spectrogram of the audio input (must specify pix_fmt if input is audio)
  >>> I = ffmpegio.image.read('myaudio.mp3', filter_complex='showspectrumpic=s=960x540', pix_fmt='rgb24')


Read Video Files
^^^^^^^^^^^^^^^^

.. code-block:: python

  >>> # read 50 video frames at t=00:32:40 then convert to grayscale
  >>> fs, F = ffmpegio.video.read('myvideo.mp4', ss='00:32:40', vframes=50, pix_fmt='gray')
  >>> #  fs: frame rate in frames/second, F: [nframes x height x width x ncomp] numpy array

  >>> # get running spectrogram of audio input (must specify pix_fmt if input is audio)
  >>> fs, F = ffmpegio.video.read('myvideo.mp4', pix_fmt='rgb24', filter_complex='showspectrum=s=1280x480')


Read Multiple Files or Streams
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: python

  >>> # read both video and audio streams (1 ea)
  >>> rates, data = ffmpegio.media.read('mymedia.mp4')
  >>> #  rates: dict of frame rate and sampling rate: keys="v:0" and "a:0"
  >>> #  data: dict of video frame array and audio sample array: keys="v:0" and "a:0"

  >>> # combine video and audio files
  >>> rates, data = ffmpegio.media.read('myvideo.mp4','myaudio.mp3')

  >>> # get output of complex filtergraph (can take multiple inputs)
  >>> expr = "[v:0]split=2[out0][l1];[l1]edgedetect[out1]"
  >>> rates, data = ffmpegio.media.read('myvideo.mp4',filter_complex=expr,map=['[out0]','[out1]'])
  >>> #  rates: dict of frame rates: keys="v:0" and "v:1"
  >>> #  data: dict of video frame arrays: keys="v:0" and "v:1"

Write Audio, Image, & Video Files
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: python

  >>> # create a video file from a numpy array
  >>> ffmpegio.video.write('myvideo.mp4', rate, F)

  >>> # create an image file from a numpy array
  >>> ffmpegio.image.write('myimage.png', F)

  >>> # create an audio file from a numpy array
  >>> ffmpegio.audio.write('myaudio.mp3', rate, x)

Filter Audio, Image, & Video data
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: python

  >>> # Add fade-in and fade-out effects to audio data
  >>> fs_out, y = ffmpegio.audio.filter('afade=t=in:ss=0:d=15,afade=t=out:st=875:d=25', fs_in, x)

  >>> # Apply mirror effect to an image
  >>> I_out = ffmpegio.image.filter('crop=iw/2:ih:0:0,split[left][tmp];[tmp]hflip[right];[left][right] hstack', I_in)

  >>> # Add text at the center of the video frame
  >>> filter = "drawtext=fontsize=30:fontfile=FreeSerif.ttf:text='hello world':x=(w-text_w)/2:y=(h-text_h)/2"
  >>> fs_out, F_out = ffmpegio.video.filter(filter, fs_in, F_in)

Stream I/O
^^^^^^^^^^

.. code-block:: python

  >>> # process video 100 frames at a time and save output as a new video 
  >>> # with the same frame rate
  >>> with ffmpegio.open('myvideo.mp4', 'rv', blocksize=100) as fin,
  >>>      ffmpegio.open('myoutput.mp4', 'wv', rate=fin.frame_rate) as fout:
  >>>     for frames in fin:
  >>>         fout.write(myprocess(frames))


Progress callback
^^^^^^^^^^^^^^^^^

  >>> import pprint

  >>> # progress callback
  >>> def progress(info, done):
  >>>     pprint(info) # bunch of stats
  >>>     if done:
  >>>        print('video decoding completed')
  >>>     else:
  >>>        return check_cancel_command(): # return True to kill immediately
  
  >>> # can be used in any butch processing
  >>> rate, F = ffmpegio.video.read('myvideo.mp4', progress=progress)

  >>> # as well as for stream processing
  >>> with ffmpegio.open('myvideo.mp4', 'rv', blocksize=100, progress=progress) as fin:
  >>>     for frames in fin:
  >>>         myprocess(frames)


