|
2 | 2 | "cells": [
|
3 | 3 | {
|
4 | 4 | "cell_type": "code",
|
5 |
| - "execution_count": 116, |
| 5 | + "execution_count": 1, |
6 | 6 | "metadata": {},
|
7 | 7 | "outputs": [],
|
8 | 8 | "source": [
|
|
15 | 15 | },
|
16 | 16 | {
|
17 | 17 | "cell_type": "code",
|
18 |
| - "execution_count": 117, |
| 18 | + "execution_count": 2, |
19 | 19 | "metadata": {},
|
20 | 20 | "outputs": [],
|
21 | 21 | "source": [
|
22 | 22 | "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", |
24 | 24 | "width = int(video_info['width'])\n",
|
25 | 25 | "height = int(video_info['height'])\n",
|
26 | 26 | "num_frames = int(video_info['nb_frames'])"
|
27 | 27 | ]
|
28 | 28 | },
|
29 | 29 | {
|
30 | 30 | "cell_type": "code",
|
31 |
| - "execution_count": 118, |
| 31 | + "execution_count": 3, |
32 | 32 | "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 | + ], |
34 | 49 | "source": [
|
35 | 50 | "out, err = (\n",
|
36 | 51 | " ffmpeg\n",
|
|
42 | 57 | " np\n",
|
43 | 58 | " .frombuffer(out, np.uint8)\n",
|
44 | 59 | " .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,:,:,:])" |
46 | 65 | ]
|
47 | 66 | },
|
48 | 67 | {
|
49 | 68 | "cell_type": "code",
|
50 |
| - "execution_count": 115, |
| 69 | + "execution_count": 4, |
51 | 70 | "metadata": {},
|
52 | 71 | "outputs": [
|
53 | 72 | {
|
54 | 73 | "data": {
|
55 | 74 | "application/vnd.jupyter.widget-view+json": {
|
56 |
| - "model_id": "17d13d7551114fb39a1fad933cf0398a", |
| 75 | + "model_id": "84bcac52195f47f8854f09acd7666b84", |
57 | 76 | "version_major": 2,
|
58 | 77 | "version_minor": 0
|
59 | 78 | },
|
60 | 79 | "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…" |
62 | 81 | ]
|
63 | 82 | },
|
64 | 83 | "metadata": {},
|
65 | 84 | "output_type": "display_data"
|
66 | 85 | }
|
67 | 86 | ],
|
68 | 87 | "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)" |
72 | 178 | ]
|
73 | 179 | },
|
| 180 | + { |
| 181 | + "cell_type": "code", |
| 182 | + "execution_count": null, |
| 183 | + "metadata": {}, |
| 184 | + "outputs": [], |
| 185 | + "source": [] |
| 186 | + }, |
74 | 187 | {
|
75 | 188 | "cell_type": "code",
|
76 | 189 | "execution_count": null,
|
|
0 commit comments