Skip to content

rho-sk/PyAV

 
 

Repository files navigation

PyAV

GitHub Test Status
Gitter Chat Documentation
Python Package Index Conda Forge


PyAV with custom ffmpeg "hack" for NTP

Prepare custom ffmpeg in docker container

Patched ffmpeg version is 4.1.6 Patch adds following data to AVPacket struct

    uint32_t timestamp;
    uint32_t last_rtcp_ntp_time_l;
    uint32_t last_rtcp_ntp_time_h;
    uint32_t last_rtcp_timestamp;
    uint16_t seq;
    bool synced;

Build in docker 20.04 with python 3.8

cd custom_ffmpeg/ffmpeg.4.1.6
bash ./build.base.patched.image.sh

Takes some time, because ffmpeg libs are built too. This will prepre local container tagged as ffmpeg_patched:4.1.6

Build release of PyAV with custom ffmpeg

bash ./av-ntp-ts.build.release.sh

final av_ntp_ts-9.2.0-cp38-cp38-linux_x86_64.whl is in ./dist folder

TODO.1

  1. final package named as av-ntp-ts, to be different than av
  2. thats why it can be published to PyPi as public package
  3. add twine script to publish whl

TODO.2

  1. windows build

Explanation

Packet class (av/packet.pyx) is extended to adress AVPacket data

    property rtcp_synced:
        """
        :type: bint
        """
        def __get__(self):
            return self.ptr.synced


    property rtcp_last_ntp_time_l:
        """
        :type: uint32_t
        """
        def __get__(self):
            return self.ptr.last_rtcp_ntp_time_l

    property rtcp_last_ntp_time_h:
        """
        :type: uint32_t
        """
        def __get__(self):
            return self.ptr.last_rtcp_ntp_time_h


    property rtcp_last_timestamp:
        """
        :type: uint32_t
        """
        def __get__(self):
            return self.ptr.last_rtcp_timestamp

    property rtcp_timestamp:
        """
        :type: uint32_t
        """
        def __get__(self):
            return self.ptr.timestamp

    property rtcp_seq:
        """
        :type: uint16_t
        """
        def __get__(self):
            return self.ptr.seq

And can be used directly in code as.

   if packet.rtcp_synced:
        print(
              f'Packet rtcp_last_ntp_time_l {packet.rtcp_last_ntp_time_l} rtcp_last_ntp_time_h {packet.rtcp_last_ntp_time_h}')
        print(f'       rtcp_last_timestamp {packet.rtcp_last_timestamp} rtcp_timestamp {packet.rtcp_timestamp}')

Those are "raw" values, and final timestamp can be calculated as follows (fragment from mv-extractor project)

    // wait for the first RTCP sender report containing RTP timestamp <-> NTP walltime mapping,
    // before this no reliable frame timestmap can be computed
    if (this->is_rtsp && packet.synced) {
        // compute absolute UNIX timestamp for each frame as follows (90 kHz clock as in RTP spec):
        // frame_time_unix = last_rtcp_ntp_time_unix + (timestamp - last_rtcp_timestamp) / 90000
        struct timeval tv;
        ntp2tv(&packet.last_rtcp_ntp_time, &tv);
        double rtp_diff = (double)(packet.timestamp - packet.last_rtcp_timestamp) / 90000.0;
        this->frame_timestamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0 + rtp_diff;
#ifdef DEBUG
        std::cerr << "frame_timestamp (UNIX): " << std::fixed << this->frame_timestamp << std::endl;
#endif
    }

PyAV is a Pythonic binding for the FFmpeg libraries. We aim to provide all of the power and control of the underlying library, but manage the gritty details as much as possible.

PyAV is for direct and precise access to your media via containers, streams, packets, codecs, and frames. It exposes a few transformations of that data, and helps you get your data to/from other packages (e.g. Numpy and Pillow).

This power does come with some responsibility as working with media is horrendously complicated and PyAV can't abstract it away or make all the best decisions for you. If the ffmpeg command does the job without you bending over backwards, PyAV is likely going to be more of a hindrance than a help.

But where you can't work without it, PyAV is a critical tool.

Installation

Due to the complexity of the dependencies, PyAV is not always the easiest Python package to install from source. Since release 8.0.0 binary wheels are provided on PyPI for Linux, Mac and Windows linked against a modern FFmpeg. You can install these wheels by running:

pip install av

If you want to use your existing FFmpeg, the source version of PyAV is on PyPI too:

pip install av --no-binary av

Alternative installation methods

Another way of installing PyAV is via conda-forge:

conda install av -c conda-forge

See the Conda install docs to get started with (mini)Conda.

And if you want to build from the absolute source (for development or testing):

git clone git@github.com:PyAV-Org/PyAV
cd PyAV
source scripts/activate.sh

# Either install the testing dependencies:
pip install --upgrade -r tests/requirements.txt
# or have it all, including FFmpeg, built/installed for you:
./scripts/build-deps

# Build PyAV.
make

Have fun, read the docs, come chat with us, and good luck!

About

Pythonic bindings for FFmpeg's libraries.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 63.9%
  • Cython 19.1%
  • Python 13.5%
  • Dockerfile 2.9%
  • Other 0.6%