FFPyPlayer is a open source FFmpeg based Python media player that supports playing media files, USB cams, ethernet cams. It is written in Cython to get c-level performance with ease of use of Python. See the documentation for full details.

Kivy uses FFPyPlayer as its video/audio backend on iOS and Android and supports it as a optional backend on all other platforms.


The player in FFPyPlayer is a python/cython port of ffplay (written in C) that I implemented using OOP and meets all the requirements below. It is high performance, including zero frame copying after decoding.

The image utilities and media writer is an OOP interface to the FFmpeg low-level C-API. It currently only supports video and no audio.

FFPyPlayer supports:


Working in a neuroscience lab, we needed a lightweight and Pythonic way to read video from webcams and other media sources and to record them to disk. E.g. in one experiment, we needed to record animal behavior from 8 cameras simultaneously without losing any frames. Some requirements were:

FFmpeg, likely the most commonly used media library, provides a C-API that meets all these needs. It has a demo ffplay implementation to play media from which FFPyPlayer is ported.

Example usage

Converting Images

from ffpyplayer.pic import Image, SWScale
# create image
w, h = 500, 100
size = w * h * 3
buf = bytearray([int(x * 255 / size) for x in range(size)])

img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))
# create image converter
sws = SWScale(w, h, img.get_pixel_format(), ofmt='yuv420p')

# convert image
img2 = sws.scale(img)
planes = img2.to_bytearray()
map(len, planes)
[50000, 12500, 12500, 0]

Simple transcoding example

from ffpyplayer.player import MediaPlayer
from ffpyplayer.writer import MediaWriter
import time, weakref

# only video
ff_opts={'an':True, 'sync':'video'}
player = MediaPlayer(filename, ff_opts=ff_opts)
# wait for size to be initialized (todo: add timeout and check for quitting)
while player.get_metadata()['src_vid_size'] == (0, 0):

frame_size = player.get_metadata()['src_vid_size']
# use the same size as the inputs
out_opts = {'pix_fmt_in':'rgb24', 'width_in':frame_size[0],
            'height_in':frame_size[1], 'codec':'rawvideo',
            'frame_rate':(30, 1)}

writer = MediaWriter(filename_out, [out_opts])
while 1:
    frame, val = player.get_frame()
    if val == 'eof':
    elif frame is None:
        img, t = frame
        writer.write_frame(img=img, pts=t, stream=0)