-
Notifications
You must be signed in to change notification settings - Fork 41
/
mp4.py
85 lines (72 loc) · 2.4 KB
/
mp4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# Copyright 2014, Sandia Corporation. Under the terms of Contract
# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain
# rights in this software.
"""Generate MPEG-4 videos."""
from __future__ import absolute_import
from __future__ import division
import os
import subprocess
import toyplot.png
for path in os.environ["PATH"].split(os.pathsep):
if os.path.exists(os.path.join(path, "ffmpeg")):
break
else:
raise Exception("An ffmpeg executable is required.") # pragma: no cover
def render(
canvas,
filename,
width=None,
height=None,
scale=None,
progress=None):
"""Render a canvas as an MPEG-4 video.
By default, the canvas dimensions in CSS pixels are mapped directly to
pixels in the output MPEG-4 video. Use one of `width`, `height`, or
`scale` to override this behavior.
Parameters
----------
canvas: :class:`toyplot.canvas.Canvas`
Canvas to be rendered.
filename: string
Output video filename.
width: number, optional
Specify the width of the output video in pixels.
height: number, optional
Specify the height of the output video in pixels.
scale: number, optional
Ratio of output video pixels to `canvas` drawing units.
progress: callback function taking a single `frame` argument, optional
Callback function that will receive the number of each frame as it's
written; useful to provide an indication of progress to end-users.
Notes
-----
The individual video frames are rendered using PNG representations
of the canvas generated with :func:`toyplot.png.render_frames()`.
Examples
--------
>>> def callback(frame):
... print "Writing frame %s" % frame
... toyplot.mp4.render(canvas, "test.mp4", progress=callback)
"""
command = [
"ffmpeg",
"-f", "image2pipe",
"-c", "png",
"-i", "-",
"-pix_fmt", "yuv420p",
"-y",
filename,
]
ffmpeg = subprocess.Popen(
command,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
for frame, png in enumerate(
toyplot.png.render_frames(
canvas=canvas, width=width, height=height, scale=scale)):
if progress is not None:
progress(frame)
ffmpeg.stdin.write(png)
ffmpeg.stdin.close()
ffmpeg.wait()