8000 Merge pull request #94 from kkroening/jupyter-demo · Powercoder64/ffmpeg-python@3520e93 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3520e93

Browse files
authored
Merge pull request kkroening#94 from kkroening/jupyter-demo
Add jupyter demo
2 parents a0caa7b + 2c9b392 commit 3520e93

File tree

6 files changed

+134
-13
lines changed

6 files changed

+134
-13
lines changed

doc/jupyter-demo.gif

912 KB
Loading

examples/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ out, _ = (ffmpeg
5757
)
5858
```
5959

60-
## [JupyterLab/Notebook widgets](https://github.com/kkroening/ffmpeg-python/blob/master/examples/ffmpeg-numpy.ipynb)
60+
## [Jupyter Frame Viewer](https://github.com/kkroening/ffmpeg-python/blob/master/examples/ffmpeg-numpy.ipynb)
6161

6262
<img src="https://raw.githubusercontent.com/kkroening/ffmpeg-python/master/doc/jupyter-screenshot.png" alt="jupyter screenshot" width="75%" />
6363

64+
## [Jupyter Pipeline Editor](https://github.com/kkroening/ffmpeg-python/blob/master/examples/ffmpeg-numpy.ipynb)
65+
66+
<img src="https://raw.githubusercontent.com/kkroening/ffmpeg-python/master/doc/jupyter-demo.png" alt="jupyter demo" width="75%" />

examples/ffmpeg-numpy.ipynb

Lines changed: 125 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"cells": [
33
{
44
"cell_type": "code",
5-
"execution_count": 116,
5+
"execution_count": 1,
66
"metadata": {},
77
"outputs": [],
88
"source": [
@@ -15,22 +15,37 @@
1515
},
1616
{
1717
"cell_type": "code",
18-
"execution_count": 117,
18+
"execution_count": 2,
1919
"metadata": {},
2020
"outputs": [],
2121
"source": [
2222
"probe = ffmpeg.probe('in.mp4')\n",
23-
"video_info = next(stream for stream in probe['streams'] if stream['codec_type'] == 'video')\n",
23+
"video_info = next(s for s in probe['streams'] if s['codec_type'] == 'video')\n",
2424
"width = int(video_info['width'])\n",
2525
"height = int(video_info['height'])\n",
2626
"num_frames = int(video_info['nb_frames'])"
2727
]
2828
},
2929
{
3030
"cell_type": "code",
31-
"execution_count": 118,
31+
"execution_count": 3,
3232
"metadata": {},
33-
"outputs": [],
33+
"outputs": [
34+
{
35+
"data": {
36+
"application/vnd.jupyter.widget-view+json": {
37+
"model_id": "5f63dc164956464c994ec58d86ee7cd9",
38+
"version_major": 2,
39+
"version_minor": 0
40+
},
41+
"text/plain": [
42+
"interactive(children=(IntSlider(value=0, description='frame', max=209), Output()), _dom_classes=('widget-inter…"
43+
]
44+
},
45+
"metadata": {},
46+
"output_type": "display_data"
47+
}
48+
],
3449
"source": [
3550
"out, err = (\n",
3651
" ffmpeg\n",
@@ -42,35 +57,133 @@
4257
" np\n",
4358
" .frombuffer(out, np.uint8)\n",
4459
" .reshape([-1, height, width, 3])\n",
45-
")"
60+
")\n",
61+
"\n",
62+
"@interact(frame=(0, num_frames))\n",
63+
"def show_frame(frame=0):\n",
64+
" plt.imshow(video[frame,:,:,:])"
4665
]
4766
},
4867
{
4968
"cell_type": "code",
50-
"execution_count": 115,
69+
"execution_count": 4,
5170
"metadata": {},
5271
"outputs": [
5372
{
5473
"data": {
5574
"application/vnd.jupyter.widget-view+json": {
56-
"model_id": "17d13d7551114fb39a1fad933cf0398a",
75+
"model_id": "84bcac52195f47f8854f09acd7666b84",
5776
"version_major": 2,
5877
"version_minor": 0
5978
},
6079
"text/plain": [
61-
"interactive(children=(IntSlider(value=0, description='frame', max=209), Output()), _dom_classes=('widget-inter"
80+
"interactive(children=(Checkbox(value=True, description='enable_overlay'), Checkbox(value=True, description='en"
6281
]
6382
},
6483
"metadata": {},
6584
"output_type": "display_data"
6685
}
6786
],
6887
"source": [
69-
"@interact(frame=(0, num_frames))\n",
70-
"def show_frame(frame=0):\n",
71-
" plt.imshow(video[frame,:,:,:])"
88+
"from io import BytesIO\n",
89+
"from PIL import Image\n",
90+
"\n",
91+
"\n",
92+
"def extract_frame(stream, frame_num):\n",
93+
" while isinstance(stream, ffmpeg.nodes.OutputStream):\n",
94+
" stream = stream.node.incoming_edges[0].upstream_node.stream()\n",
95+
" out, _ = (\n",
96+
" stream\n",
97+
" .filter_('select', 'gte(n,{})'.format(frame_num))\n",
98+
" .output('pipe:', format='rawvideo', pix_fmt='rgb24', vframes=1)\n",
99+
" .run(capture_stdout=True, capture_stderr=True)\n",
100+
" )\n",
101+
" return np.frombuffer(out, np.uint8).reshape([height, width, 3])\n",
102+
"\n",
103+
"\n",
104+
"def png_to_np(png_bytes):\n",
105+
" buffer = BytesIO(png_bytes)\n",
106+
" pil_image = Image.open(buffer)\n",
107+
" return np.array(pil_image)\n",
108+
" \n",
109+
"\n",
110+
"def build_graph(\n",
111+
" enable_overlay, flip_overlay, enable_box, box_x, box_y,\n",
112+
" thickness, color):\n",
113+
"\n",
114+
" stream = ffmpeg.input('in.mp4')\n",
115+
"\n",
116+
" if enable_overlay:\n",
117+
" overlay = ffmpeg.input('overlay.png')\n",
118+
" if flip_overlay:\n",
119+
" overlay = overlay.hflip()\n",
120+
" stream = stream.overlay(overlay)\n",
121+
"\n",
122+
" if enable_box:\n",
123+
" stream = stream.drawbox(\n",
124+
" box_x, box_y, 120, 120, color=color, t=thickness)\n",
125+
"\n",
126+
" return stream.output('out.mp4')\n",
127+
"\n",
128+
"\n",
129+
"def show_image(ax, stream, frame_num):\n",
130+
" try:\n",
131+
" image = extract_frame(stream, frame_num)\n",
132+
" ax.imshow(image)\n",
133+
" ax.axis('off')\n",
134+
" except ffmpeg.Error as e:\n",
135+
" print(e.stderr.decode())\n",
136+
"\n",
137+
"\n",
138+
"def show_graph(ax, stream, detail):\n",
139+
" data = ffmpeg.view(stream, detail=detail, pipe=True)\n",
140+
" image = png_to_np(data)\n",
141+
" ax.imshow(image, aspect='equal', interpolation='hanning')\n",
142+
" ax.set_xlim(0, 1100)\n",
143+
" ax.axis('off')\n",
144+
"\n",
145+
"\n",
146+
"@interact(\n",
147+
" frame_num=(0, num_frames),\n",
148+
" box_x=(0, 200),\n",
149+
" box_y=(0, 200),\n",
150+
" thickness=(1, 40),\n",
151+
" color=['red', 'green', 'magenta', 'blue'],\n",
152+
")\n",
153+
"def f(\n",
154+
" enable_overlay=True,\n",
155+
" enable_box=True,\n",
156+
" flip_overlay=True,\n",
157+
" graph_detail=False,\n",
158+
" frame_num=0,\n",
159+
" box_x=50,\n",
160+
" box_y=50,\n",
161+
" thickness=5,\n",
162+
" color='red'):\n",
163+
"\n",
164+
" stream = build_graph(\n",
165+
" enable_overlay,\n",
166+
" flip_overlay,\n",
167+
" enable_box,\n",
168+
" box_x,\n",
169+
" box_y,\n",
170+
" thickness,\n",
171+
" color\n",
172+
" )\n",
173+
"\n",
174+
" fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(15,4))\n",
175+
" plt.tight_layout()\n",
176+
" show_image(ax0, stream, frame_num)\n",
177+
" show_graph(ax1, stream, graph_detail)"
72178
]
73179
},
180+
{
181+
"cell_type": "code",
182+
"execution_count": null,
183+
"metadata": {},
184+
"outputs": [],
185+
"source": []
186+
},
74187
{
75188
"cell_type": "code",
76189
"execution_count": null,

examples/in.mp4

329 KB
Binary file not shown.

examples/overlay.png

2.16 KB
Loading

examples/requirements.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
ffmpeg-python
22
gevent
33
google-cloud-speech
4+
graphviz
5+
ipywidgets
6+
jupyter
7+
matplotlib
8+
Pillow
49
tqdm

0 commit comments

Comments
 (0)
0