-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy path_typing.py
More file actions
465 lines (345 loc) · 16.6 KB
/
_typing.py
File metadata and controls
465 lines (345 loc) · 16.6 KB
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
"""ffmpegio object independent common type hints"""
from __future__ import annotations
from fractions import Fraction
from typing_extensions import *
if TYPE_CHECKING:
from namedpipe import NPopen
from .threading import CopyFileObjThread
# from typing_extensions import *
FFmpegOptionDict = dict[str, Any]
"""FFmpeg options with their values keyed by the option names without preceding dash.
For option flags (e.g., -y) without any value, use `None` or its alias `ffmpegio.FLAG`"""
RawDataBlob = Any
"""any object to represent raw binary data supported by a data I/O plugin."""
DTypeString = LiteralString
"""Numpy array interface protocol typestr string
The string format consists of 3 parts: a character describing the byteorder of the data
(`'<'`: little-endian, `'>'`: big-endian, `'|'`: not-relevant), a character code giving
the basic type of the array, and an integer providing the number of bytes the type uses.
Three basic type character codes are relevant to `ffmpegio` package:
===== ================
code description
===== ================
`'i'` Integer
`'u'` Unsigned integer
`'f'` Floating point
===== ================
See https://numpy.org/doc/stable/reference/arrays.interface.html for Numpy's
official documentation.
"""
ShapeTuple = tuple[int, ...]
"""Tuple whose elements are the array size in each dimension. Each entry is an integer (a Python int)."""
RawStreamDef = tuple[int | Fraction, RawDataBlob] | tuple[RawDataBlob, FFmpegOptionDict]
"""2-element tuple to define a raw stream data
It comes in two forms: rate-data or data-option. The rate-data form specifies
a pair of the frame rate (video) or sampling rate (audio) and the data blob.
The data-option form specifies the data blob and its FFmpeg options. Note
that a data-option tuple is only valid if its option dict contains the rate
field: `r` for video or `ar` for audio.
"""
RawStreamInfoTuple = tuple[DTypeString, ShapeTuple, int | Fraction]
"""3-element tuple (dtype, shape, rate) to characterize raw data stream"""
ProgressCallable = Callable[[dict[str, Any], bool], bool]
"""FFmpeg progress callback function
callback(status, done)
status - dict of encoding status
done - True if the last callback
The callback may return True to cancel the FFmpeg execution.
"""
MediaType = Literal["audio", "video"]
"""supported media stream types
=============== ================================================================
value description
=============== ================================================================
`'video'` video stream
`'audio'` audio stream
=============== ================================================================
"""
FFmpegMediaType = Literal["video", "audio", "subtitle", "data", "attachments"]
"""FFmpeg media stream types
=============== ================================================================
value description
=============== ================================================================
`'video'` video stream
`'audio'` audio stream
`'subtitle'` subtitle stream
`'data'` data stream
`'attachments'` attachments stream
=============== ================================================================
"""
FFmpegUrlType = str
"""input and output file/stream urls (str or a stringifiable object)
"""
FFmpegInputType = Literal["url", "filtergraph", "buffer", "fileobj"]
"""mechanisms to feed encoded input data to FFmpeg input pipe
=============== ================================================================
value description
=============== ================================================================
`'url'` path to the input file or streaming url
`'filtergraph'` input filtergraph
`'buffer'` binary input data given as a bytes-like object or to be piped in
`'fileobj'` open readable file object
=============== ================================================================
"""
FFmpegOutputType = Literal["url", "fileobj", "buffer"]
"""mechanisms to extract encoded output data from FFmpeg output pipe
=============== ============================================================================
value description
=============== ============================================================================
`'url'` path to the output file or streaming url
`'buffer'` buffer output data as `RawDataBlob` (raw stream) or `bytes` (encoded stream)
`'fileobj'` open readable file object
=============== ============================================================================
"""
##################
# Plugin protocols
##################
class GetInfoCallable(Protocol):
"""Plugin function prototype to get information of a raw data blob object
A plugin may implement this prototype with `audio_info()` for audio stream or
`video_info()` for video/image stream.
:param obj: Plugin-specific raw data blob object
:return shape: tuple of `int`s of the raw data shape
:return dtype: numpy dtype string of a video/image pixel or an audio sample
"""
def __call__(self, *, obj: object) -> tuple[ShapeTuple, DTypeString]: ...
class ToBytesCallable(Protocol):
"""Plugin function prototype to convert raw data blob object to a byte buffer
A plugin may implement this prototype with `audio_bytes()` for audio stream or
`video_bytes()` for video/image stream.
:param obj: Plugin-specific raw data blob object
:return: a FFmpeg raw media stream compatible bytes
"""
def __call__(self, *, obj: object) -> memoryview: ...
class CountDataCallable(Protocol):
"""Plugin function prototype to count a number of video frames/audio samples
A plugin may implement this prototype with `audio_samples()` for audio stream or
`video_frames()` for video/image stream.
:param obj: Plugin-specific raw data blob object
:return: number of video frames or of audio samples
"""
def __call__(self, *, obj: object) -> int: ...
class FromBytesCallable(Protocol):
"""Plugin function prototype to convert FFmpeg output bytes to raw data blob
A plugin may implement this prototype with `bytes_to_audio()` for audio stream or
`bytes_to_video()` for video stream.
:param b: FFmpeg output of raw audio/video/image frames
:param dtype: numpy dtype string of pixel/sample data format
:param shape: tuple of the dimension of one video frame or one audio sample.
Audio: (channels,), Video: (height, width, components)
:param squeeze: True to remove all dimensions with length 1
:return: Plugin-specific raw data blob object
"""
def __call__(
self, b: bytes, dtype: DTypeString, shape: ShapeTuple, squeeze: bool
) -> object: ...
class IsEmptyCallable(Protocol):
"""Plugin function prototype to check if data blob contains no data
A plugin may implement this prototype with `audio_samples()` for audio stream or
`video_frames()` for video/image stream.
:param obj: Plugin-specific raw data blob object
:return: True if the blob contains no data
"""
def __call__(self, *, obj: object) -> bool: ...
######
class RawInputInfoDict(TypedDict):
"""raw input media stream information
=============== ================================================================
key description
=============== ================================================================
`'src_type'` always `'buffer'`
`'media_type'` media stream identifier: `'audio'` or '`video'`
`'raw_info'` tuple of (rate, shape, dtype)
`'item_size` size of each frame/sample in bytes
`'data2bytes'` conversion function
`'data_is_empty'` function to check empty data frame
`'data_count'` function to count number of frames/samples in a blob
`'buffer'` (optional) known media data blobs to be input (typically for
a batch operation)
`'pipe'` (optional) named pipe assigned to this data stream
`'writer'` (optional) writer thread assigned to this data stream
=============== ================================================================
"""
src_type: Literal["buffer"]
"""True if file path/url"""
media_type: MediaType
"""media type if input pipe"""
raw_info: RawStreamInfoTuple
"""tuple of (rate, shape, dtype)"""
item_size: int
"""size of each frame/sample in bytes"""
data2bytes: ToBytesCallable
"""converts a Python data blob to raw media bytes"""
data_is_empty: IsEmptyCallable
"""returns True if the data blob is empty"""
data_count: CountDataCallable
"""returns number of frames in the data blob"""
buffer: NotRequired[object]
"""stores data blob (typically for batch operation)"""
class UrlEncodedInputInfoDict(TypedDict):
"""url/filtergraph encoded input source info"""
src_type: Literal["url", "filtergraph"]
"""input data is from a url/file or from an input filtergraph"""
class PipedEncodedInputInfoDict(TypedDict):
"""piped encoded input source info"""
src_type: Literal["buffer"]
buffer: NotRequired[bytes] # index of the source index
class FileObjEncodedInputInfoDict(TypedDict):
"""fileobj encoded input info"""
src_type: Literal["fileobj"]
fileobj: IO # file object
EncodedInputInfoDict = (
UrlEncodedInputInfoDict | PipedEncodedInputInfoDict | FileObjEncodedInputInfoDict
)
"""encoded input container stream information
=============== ================================================================
key description
=============== ================================================================
`'src_type'` `'url'`, `'filtergraph'`, `'buffer'`, or `'fileobj'`
`'buffer'` (optional for `src_type = 'buffer') known media data bytes to be
input (typically for a batch operation)
=============== ================================================================
"""
InputInfoDict = RawInputInfoDict | EncodedInputInfoDict
class PipeWriter(Protocol):
def write(self, data: bytes | None): ...
def join(self): ...
def closed(self) -> bool: ...
class PipeReader(Protocol):
def read(self, n: int = -1) -> bytes: ...
def join(self): ...
def cool_down(self): ...
class InputPipeInfoDict(TypedDict):
"""
========== ==========================================
`'pipe'` named pipe assigned to this data stream
`'writer'` writer thread assigned to this data stream
========== ==========================================
"""
pipe: NPopen | Literal["stdin"]
"""named pipe assigned to this data stream"""
writer: PipeWriter
"""writer thread assigned to this data stream"""
##################################################
class RawDirectOutputInfoDict(TypedDict):
"""raw output media stream info
=================== ================================================================
key description
=================== ================================================================
`'dst_type'` `'buffer'`
`'media_type'` media stream identifier: `'audio'` or '`video'`
`'raw_info'` tuple of (dtype, shape, rate)
`'item_size` size of each frame/sample in bytes
`'bytes2data'` function to convert bytes to raw data blob
`'data_is_empty'` function to check empty data frame
`'data_count'` function to count number of frames/samples in a blob
`'user_map'` user specified FFmpeg map option of this stream
`'squeeze'` True to squeeze output shape (remove all length-1 dims)
`'input_file_id'` input file id
`'input_stream_id'` input stream id
=================== ================================================================
"""
dst_type: Literal["buffer"] # True if file path/url
media_type: MediaType #
raw_info: RawStreamInfoTuple
bytes2data: FromBytesCallable
item_size: int
data_is_empty: IsEmptyCallable
data_count: CountDataCallable
user_map: str # user specified map option
squeeze: bool
input_file_id: NotRequired[int]
input_stream_id: NotRequired[int]
class RawFilteredOutputInfoDict(TypedDict):
"""raw output media stream info
=================== ================================================================
key description
=================== ================================================================
`'dst_type'` `'buffer'`
`'media_type'` media stream identifier: `'audio'` or '`video'`
`'raw_info'` tuple of (dtype, shape, rate)
`'item_size` size of each frame/sample in bytes
`'bytes2data'` function to convert bytes to raw data blob
`'data_is_empty'` function to check empty data frame
`'data_count'` function to count number of frames/samples in a blob
`'user_map'` user specified FFmpeg map option of this stream
`'squeeze'` True to squeeze output shape (remove all length-1 dims)
`'linklabel'` mapped filtergraph output label
=============== ================================================================
"""
dst_type: Literal["buffer"] # True if file path/url
media_type: MediaType #
raw_info: RawStreamInfoTuple
item_size: int
bytes2data: FromBytesCallable
data_is_empty: IsEmptyCallable
data_count: CountDataCallable
user_map: str # user specified map option
squeeze: bool
linklabel: str
RawOutputInfoDict = RawDirectOutputInfoDict | RawFilteredOutputInfoDict
"""raw output media stream info
=================== ================================================================
key description
=================== ================================================================
`'dst_type'` `'buffer'`
`'media_type'` media stream identifier: `'audio'` or '`video'`
`'raw_info'` tuple of (dtype, shape, rate)
`'bytes2data'` function to convert bytes to raw data blob
`'data_is_empty'` function to check empty raw data blob
`'data_count'` function to count number of frames/samples in a blob
`'squeeze'` True to squeeze output shape (remove all length-1 dims)
`'input_file_id'` (optional) input file id if there is no complex filtergraph
`'input_stream_id'` (optional) input stream id if there is no complex filtergraph
`'linklabel'` (optional) mapped filtergraph output label if there is complex
filtergraph
=============== ================================================================
"""
class UrlOrPipedEncodedOutputInfoDict(TypedDict):
"""url/filtergraph encoded input source info"""
dst_type: Literal["url", "buffer"]
"""output data goes to either a url/filepath or a pipe"""
class FileObjEncodedOutputInfoDict(TypedDict):
"""fileobj encoded input info"""
dst_type: Literal["fileobj"]
fileobj: IO # file object
EncodedOutputInfoDict = UrlOrPipedEncodedOutputInfoDict | FileObjEncodedOutputInfoDict
"""encoded output container stream information
=============== ================================================================
key description
=============== ================================================================
`'src_type'` `'url'`, `'filtergraph'`, `'buffer'`, or `'fileobj'`
`'buffer'` (optional for `src_type = 'buffer') known media data bytes to be
input (typically for a batch operation)
`'pipe'` (optional for `src_type` is `'buffer'` or `'fileobj'`)
named pipe assigned to this data stream
`'writer'` (optional for `src_type` is `'buffer'` or `'fileobj'`)
writer thread assigned to this data stream
=============== ================================================================
"""
OutputInfoDict = RawOutputInfoDict | EncodedOutputInfoDict
"""combined output info"""
class OutputPipeInfoDict(TypedDict):
"""
=============== ================================================================
`'pipe'` named pipe assigned to this data stream
`'reader'` reader thread assigned to this data stream
`'itemsize'` (optional) one frame/sample size in bytes
`'nmin'` (optional) minimum read block size
=============== ================================================================
"""
pipe: NPopen | Literal["stdout"]
reader: PipeReader | CopyFileObjThread
itemsize: NotRequired[int]
nmin: NotRequired[int]
##################################################
class AudioFilterGraphInfoDict(TypedDict):
media_type: Literal["audio"]
sample_fmt: str
ac: int
ar: int
class VideoFilterGraphInfoDict(TypedDict):
media_type: Literal["video"]
r: int | Fraction
pix_fmt: str
FilterGraphInfoDict = AudioFilterGraphInfoDict | VideoFilterGraphInfoDict