torchcodec 0.10.0__cp312-cp312-manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- torchcodec/__init__.py +27 -0
- torchcodec/_core/AVIOContextHolder.cpp +60 -0
- torchcodec/_core/AVIOContextHolder.h +64 -0
- torchcodec/_core/AVIOFileLikeContext.cpp +98 -0
- torchcodec/_core/AVIOFileLikeContext.h +55 -0
- torchcodec/_core/AVIOTensorContext.cpp +130 -0
- torchcodec/_core/AVIOTensorContext.h +44 -0
- torchcodec/_core/BetaCudaDeviceInterface.cpp +849 -0
- torchcodec/_core/BetaCudaDeviceInterface.h +196 -0
- torchcodec/_core/CMakeLists.txt +295 -0
- torchcodec/_core/CUDACommon.cpp +330 -0
- torchcodec/_core/CUDACommon.h +51 -0
- torchcodec/_core/Cache.h +124 -0
- torchcodec/_core/CpuDeviceInterface.cpp +509 -0
- torchcodec/_core/CpuDeviceInterface.h +141 -0
- torchcodec/_core/CudaDeviceInterface.cpp +602 -0
- torchcodec/_core/CudaDeviceInterface.h +79 -0
- torchcodec/_core/DeviceInterface.cpp +117 -0
- torchcodec/_core/DeviceInterface.h +191 -0
- torchcodec/_core/Encoder.cpp +1054 -0
- torchcodec/_core/Encoder.h +192 -0
- torchcodec/_core/FFMPEGCommon.cpp +684 -0
- torchcodec/_core/FFMPEGCommon.h +314 -0
- torchcodec/_core/FilterGraph.cpp +159 -0
- torchcodec/_core/FilterGraph.h +59 -0
- torchcodec/_core/Frame.cpp +47 -0
- torchcodec/_core/Frame.h +72 -0
- torchcodec/_core/Metadata.cpp +124 -0
- torchcodec/_core/Metadata.h +92 -0
- torchcodec/_core/NVCUVIDRuntimeLoader.cpp +320 -0
- torchcodec/_core/NVCUVIDRuntimeLoader.h +14 -0
- torchcodec/_core/NVDECCache.cpp +60 -0
- torchcodec/_core/NVDECCache.h +102 -0
- torchcodec/_core/SingleStreamDecoder.cpp +1586 -0
- torchcodec/_core/SingleStreamDecoder.h +391 -0
- torchcodec/_core/StreamOptions.h +70 -0
- torchcodec/_core/Transform.cpp +128 -0
- torchcodec/_core/Transform.h +86 -0
- torchcodec/_core/ValidationUtils.cpp +35 -0
- torchcodec/_core/ValidationUtils.h +21 -0
- torchcodec/_core/__init__.py +46 -0
- torchcodec/_core/_metadata.py +262 -0
- torchcodec/_core/custom_ops.cpp +1090 -0
- torchcodec/_core/fetch_and_expose_non_gpl_ffmpeg_libs.cmake +169 -0
- torchcodec/_core/nvcuvid_include/cuviddec.h +1374 -0
- torchcodec/_core/nvcuvid_include/nvcuvid.h +610 -0
- torchcodec/_core/ops.py +605 -0
- torchcodec/_core/pybind_ops.cpp +50 -0
- torchcodec/_frame.py +146 -0
- torchcodec/_internally_replaced_utils.py +68 -0
- torchcodec/_samplers/__init__.py +7 -0
- torchcodec/_samplers/video_clip_sampler.py +419 -0
- torchcodec/decoders/__init__.py +12 -0
- torchcodec/decoders/_audio_decoder.py +185 -0
- torchcodec/decoders/_decoder_utils.py +113 -0
- torchcodec/decoders/_video_decoder.py +601 -0
- torchcodec/encoders/__init__.py +2 -0
- torchcodec/encoders/_audio_encoder.py +149 -0
- torchcodec/encoders/_video_encoder.py +196 -0
- torchcodec/libtorchcodec_core4.so +0 -0
- torchcodec/libtorchcodec_core5.so +0 -0
- torchcodec/libtorchcodec_core6.so +0 -0
- torchcodec/libtorchcodec_core7.so +0 -0
- torchcodec/libtorchcodec_core8.so +0 -0
- torchcodec/libtorchcodec_custom_ops4.so +0 -0
- torchcodec/libtorchcodec_custom_ops5.so +0 -0
- torchcodec/libtorchcodec_custom_ops6.so +0 -0
- torchcodec/libtorchcodec_custom_ops7.so +0 -0
- torchcodec/libtorchcodec_custom_ops8.so +0 -0
- torchcodec/libtorchcodec_pybind_ops4.so +0 -0
- torchcodec/libtorchcodec_pybind_ops5.so +0 -0
- torchcodec/libtorchcodec_pybind_ops6.so +0 -0
- torchcodec/libtorchcodec_pybind_ops7.so +0 -0
- torchcodec/libtorchcodec_pybind_ops8.so +0 -0
- torchcodec/samplers/__init__.py +2 -0
- torchcodec/samplers/_common.py +84 -0
- torchcodec/samplers/_index_based.py +287 -0
- torchcodec/samplers/_time_based.py +358 -0
- torchcodec/share/cmake/TorchCodec/TorchCodecConfig.cmake +76 -0
- torchcodec/share/cmake/TorchCodec/ffmpeg_versions.cmake +122 -0
- torchcodec/transforms/__init__.py +12 -0
- torchcodec/transforms/_decoder_transforms.py +375 -0
- torchcodec/version.py +2 -0
- torchcodec-0.10.0.dist-info/METADATA +286 -0
- torchcodec-0.10.0.dist-info/RECORD +88 -0
- torchcodec-0.10.0.dist-info/WHEEL +5 -0
- torchcodec-0.10.0.dist-info/licenses/LICENSE +28 -0
- torchcodec-0.10.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
from torch import Tensor
|
|
5
|
+
|
|
6
|
+
from torchcodec import _core
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AudioEncoder:
|
|
10
|
+
"""An audio encoder.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
samples (``torch.Tensor``): The samples to encode. This must be a 2D
|
|
14
|
+
tensor of shape ``(num_channels, num_samples)``, or a 1D tensor in
|
|
15
|
+
which case ``num_channels = 1`` is assumed. Values must be float
|
|
16
|
+
values in ``[-1, 1]``.
|
|
17
|
+
sample_rate (int): The sample rate of the **input** ``samples``. The
|
|
18
|
+
sample rate of the encoded output can be specified using the
|
|
19
|
+
encoding methods (``to_file``, etc.).
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, samples: Tensor, *, sample_rate: int):
|
|
23
|
+
torch._C._log_api_usage_once("torchcodec.encoders.AudioEncoder")
|
|
24
|
+
# Some of these checks are also done in C++: it's OK, they're cheap, and
|
|
25
|
+
# doing them here allows to surface them when the AudioEncoder is
|
|
26
|
+
# instantiated, rather than later when the encoding methods are called.
|
|
27
|
+
if not isinstance(samples, Tensor):
|
|
28
|
+
raise ValueError(
|
|
29
|
+
f"Expected samples to be a Tensor, got {type(samples) = }."
|
|
30
|
+
)
|
|
31
|
+
if samples.ndim == 1:
|
|
32
|
+
# make it 2D and assume 1 channel
|
|
33
|
+
samples = torch.unsqueeze(samples, 0)
|
|
34
|
+
if samples.ndim != 2:
|
|
35
|
+
raise ValueError(f"Expected 1D or 2D samples, got {samples.shape = }.")
|
|
36
|
+
if samples.dtype != torch.float32:
|
|
37
|
+
raise ValueError(f"Expected float32 samples, got {samples.dtype = }.")
|
|
38
|
+
if sample_rate <= 0:
|
|
39
|
+
raise ValueError(f"{sample_rate = } must be > 0.")
|
|
40
|
+
|
|
41
|
+
self._samples = samples
|
|
42
|
+
self._sample_rate = sample_rate
|
|
43
|
+
|
|
44
|
+
def to_file(
|
|
45
|
+
self,
|
|
46
|
+
dest: str | Path,
|
|
47
|
+
*,
|
|
48
|
+
bit_rate: int | None = None,
|
|
49
|
+
num_channels: int | None = None,
|
|
50
|
+
sample_rate: int | None = None,
|
|
51
|
+
) -> None:
|
|
52
|
+
"""Encode samples into a file.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
dest (str or ``pathlib.Path``): The path to the output file, e.g.
|
|
56
|
+
``audio.mp3``. The extension of the file determines the audio
|
|
57
|
+
format and container.
|
|
58
|
+
bit_rate (int, optional): The output bit rate. Encoders typically
|
|
59
|
+
support a finite set of bit rate values, so ``bit_rate`` will be
|
|
60
|
+
matched to one of those supported values. The default is chosen
|
|
61
|
+
by FFmpeg.
|
|
62
|
+
num_channels (int, optional): The number of channels of the encoded
|
|
63
|
+
output samples. By default, the number of channels of the input
|
|
64
|
+
``samples`` is used.
|
|
65
|
+
sample_rate (int, optional): The sample rate of the encoded output.
|
|
66
|
+
By default, the sample rate of the input ``samples`` is used.
|
|
67
|
+
"""
|
|
68
|
+
_core.encode_audio_to_file(
|
|
69
|
+
samples=self._samples,
|
|
70
|
+
sample_rate=self._sample_rate,
|
|
71
|
+
filename=str(dest),
|
|
72
|
+
bit_rate=bit_rate,
|
|
73
|
+
num_channels=num_channels,
|
|
74
|
+
desired_sample_rate=sample_rate,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def to_tensor(
|
|
78
|
+
self,
|
|
79
|
+
format: str,
|
|
80
|
+
*,
|
|
81
|
+
bit_rate: int | None = None,
|
|
82
|
+
num_channels: int | None = None,
|
|
83
|
+
sample_rate: int | None = None,
|
|
84
|
+
) -> Tensor:
|
|
85
|
+
"""Encode samples into raw bytes, as a 1D uint8 Tensor.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
format (str): The format of the encoded samples, e.g. "mp3", "wav"
|
|
89
|
+
or "flac".
|
|
90
|
+
bit_rate (int, optional): The output bit rate. Encoders typically
|
|
91
|
+
support a finite set of bit rate values, so ``bit_rate`` will be
|
|
92
|
+
matched to one of those supported values. The default is chosen
|
|
93
|
+
by FFmpeg.
|
|
94
|
+
num_channels (int, optional): The number of channels of the encoded
|
|
95
|
+
output samples. By default, the number of channels of the input
|
|
96
|
+
``samples`` is used.
|
|
97
|
+
sample_rate (int, optional): The sample rate of the encoded output.
|
|
98
|
+
By default, the sample rate of the input ``samples`` is used.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Tensor: The raw encoded bytes as 1D uint8 Tensor.
|
|
102
|
+
"""
|
|
103
|
+
return _core.encode_audio_to_tensor(
|
|
104
|
+
samples=self._samples,
|
|
105
|
+
sample_rate=self._sample_rate,
|
|
106
|
+
format=format,
|
|
107
|
+
bit_rate=bit_rate,
|
|
108
|
+
num_channels=num_channels,
|
|
109
|
+
desired_sample_rate=sample_rate,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def to_file_like(
|
|
113
|
+
self,
|
|
114
|
+
file_like,
|
|
115
|
+
format: str,
|
|
116
|
+
*,
|
|
117
|
+
bit_rate: int | None = None,
|
|
118
|
+
num_channels: int | None = None,
|
|
119
|
+
sample_rate: int | None = None,
|
|
120
|
+
) -> None:
|
|
121
|
+
"""Encode samples into a file-like object.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
file_like: A file-like object that supports ``write()`` and
|
|
125
|
+
``seek()`` methods, such as io.BytesIO(), an open file in binary
|
|
126
|
+
write mode, etc. Methods must have the following signature:
|
|
127
|
+
``write(data: bytes) -> int`` and ``seek(offset: int, whence:
|
|
128
|
+
int = 0) -> int``.
|
|
129
|
+
format (str): The format of the encoded samples, e.g. "mp3", "wav"
|
|
130
|
+
or "flac".
|
|
131
|
+
bit_rate (int, optional): The output bit rate. Encoders typically
|
|
132
|
+
support a finite set of bit rate values, so ``bit_rate`` will be
|
|
133
|
+
matched to one of those supported values. The default is chosen
|
|
134
|
+
by FFmpeg.
|
|
135
|
+
num_channels (int, optional): The number of channels of the encoded
|
|
136
|
+
output samples. By default, the number of channels of the input
|
|
137
|
+
``samples`` is used.
|
|
138
|
+
sample_rate (int, optional): The sample rate of the encoded output.
|
|
139
|
+
By default, the sample rate of the input ``samples`` is used.
|
|
140
|
+
"""
|
|
141
|
+
_core.encode_audio_to_file_like(
|
|
142
|
+
samples=self._samples,
|
|
143
|
+
sample_rate=self._sample_rate,
|
|
144
|
+
format=format,
|
|
145
|
+
file_like=file_like,
|
|
146
|
+
bit_rate=bit_rate,
|
|
147
|
+
num_channels=num_channels,
|
|
148
|
+
desired_sample_rate=sample_rate,
|
|
149
|
+
)
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import torch
|
|
5
|
+
from torch import Tensor
|
|
6
|
+
|
|
7
|
+
from torchcodec import _core
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class VideoEncoder:
|
|
11
|
+
"""A video encoder on CPU or CUDA..
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
frames (``torch.Tensor``): The frames to encode. This must be a 4D
|
|
15
|
+
tensor of shape ``(N, C, H, W)`` where N is the number of frames,
|
|
16
|
+
C is 3 channels (RGB), H is height, and W is width.
|
|
17
|
+
Values must be uint8 in the range ``[0, 255]``.
|
|
18
|
+
The tensor can be on CPU or CUDA. The device of the tensor
|
|
19
|
+
determines which encoder is used (CPU or GPU).
|
|
20
|
+
frame_rate (float): The frame rate of the **input** ``frames``. Also defines the encoded **output** frame rate.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, frames: Tensor, *, frame_rate: float):
|
|
24
|
+
torch._C._log_api_usage_once("torchcodec.encoders.VideoEncoder")
|
|
25
|
+
if not isinstance(frames, Tensor):
|
|
26
|
+
raise ValueError(f"Expected frames to be a Tensor, got {type(frames) = }.")
|
|
27
|
+
if frames.ndim != 4:
|
|
28
|
+
raise ValueError(f"Expected 4D frames, got {frames.shape = }.")
|
|
29
|
+
if frames.dtype != torch.uint8:
|
|
30
|
+
raise ValueError(f"Expected uint8 frames, got {frames.dtype = }.")
|
|
31
|
+
if frame_rate <= 0:
|
|
32
|
+
raise ValueError(f"{frame_rate = } must be > 0.")
|
|
33
|
+
|
|
34
|
+
self._frames = frames
|
|
35
|
+
self._frame_rate = frame_rate
|
|
36
|
+
|
|
37
|
+
def to_file(
|
|
38
|
+
self,
|
|
39
|
+
dest: str | Path,
|
|
40
|
+
*,
|
|
41
|
+
codec: str | None = None,
|
|
42
|
+
pixel_format: str | None = None,
|
|
43
|
+
crf: int | float | None = None,
|
|
44
|
+
preset: str | int | None = None,
|
|
45
|
+
extra_options: dict[str, Any] | None = None,
|
|
46
|
+
) -> None:
|
|
47
|
+
"""Encode frames into a file.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
dest (str or ``pathlib.Path``): The path to the output file, e.g.
|
|
51
|
+
``video.mp4``. The extension of the file determines the video
|
|
52
|
+
container format.
|
|
53
|
+
codec (str, optional): The codec to use for encoding (e.g., "libx264",
|
|
54
|
+
"h264"). If not specified, the default codec
|
|
55
|
+
for the container format will be used.
|
|
56
|
+
See :ref:`codec_selection` for details.
|
|
57
|
+
pixel_format (str, optional): The pixel format for encoding (e.g.,
|
|
58
|
+
"yuv420p", "yuv444p"). If not specified, uses codec's default format.
|
|
59
|
+
Must be left as ``None`` when encoding CUDA tensors.
|
|
60
|
+
See :ref:`pixel_format` for details.
|
|
61
|
+
crf (int or float, optional): Constant Rate Factor for encoding quality. Lower values
|
|
62
|
+
mean better quality. Valid range depends on the encoder (e.g. 0-51 for libx264).
|
|
63
|
+
Defaults to None (which will use encoder's default).
|
|
64
|
+
See :ref:`crf` for details.
|
|
65
|
+
preset (str or int, optional): Encoder option that controls the tradeoff between
|
|
66
|
+
encoding encoding speed and compression (output size). Valid on the encoder (commonly
|
|
67
|
+
a string: "fast", "medium", "slow"). Defaults to None
|
|
68
|
+
(which will use encoder's default).
|
|
69
|
+
See :ref:`preset` for details.
|
|
70
|
+
extra_options (dict[str, Any], optional): A dictionary of additional
|
|
71
|
+
encoder options to pass, e.g. ``{"qp": 5, "tune": "film"}``.
|
|
72
|
+
See :ref:`extra_options` for details.
|
|
73
|
+
"""
|
|
74
|
+
preset = str(preset) if isinstance(preset, int) else preset
|
|
75
|
+
_core.encode_video_to_file(
|
|
76
|
+
frames=self._frames,
|
|
77
|
+
frame_rate=self._frame_rate,
|
|
78
|
+
filename=str(dest),
|
|
79
|
+
codec=codec,
|
|
80
|
+
pixel_format=pixel_format,
|
|
81
|
+
crf=crf,
|
|
82
|
+
preset=preset,
|
|
83
|
+
extra_options=[
|
|
84
|
+
str(x) for k, v in (extra_options or {}).items() for x in (k, v)
|
|
85
|
+
],
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
def to_tensor(
|
|
89
|
+
self,
|
|
90
|
+
format: str,
|
|
91
|
+
*,
|
|
92
|
+
codec: str | None = None,
|
|
93
|
+
pixel_format: str | None = None,
|
|
94
|
+
crf: int | float | None = None,
|
|
95
|
+
preset: str | int | None = None,
|
|
96
|
+
extra_options: dict[str, Any] | None = None,
|
|
97
|
+
) -> Tensor:
|
|
98
|
+
"""Encode frames into raw bytes, as a 1D uint8 Tensor.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
format (str): The container format of the encoded frames, e.g. "mp4", "mov",
|
|
102
|
+
"mkv", "avi", "webm", "flv", etc.
|
|
103
|
+
codec (str, optional): The codec to use for encoding (e.g., "libx264",
|
|
104
|
+
"h264"). If not specified, the default codec
|
|
105
|
+
for the container format will be used.
|
|
106
|
+
See :ref:`codec_selection` for details.
|
|
107
|
+
pixel_format (str, optional): The pixel format to encode frames into (e.g.,
|
|
108
|
+
"yuv420p", "yuv444p"). If not specified, uses codec's default format.
|
|
109
|
+
Must be left as ``None`` when encoding CUDA tensors.
|
|
110
|
+
See :ref:`pixel_format` for details.
|
|
111
|
+
crf (int or float, optional): Constant Rate Factor for encoding quality. Lower values
|
|
112
|
+
mean better quality. Valid range depends on the encoder (e.g. 0-51 for libx264).
|
|
113
|
+
Defaults to None (which will use encoder's default).
|
|
114
|
+
See :ref:`crf` for details.
|
|
115
|
+
preset (str or int, optional): Encoder option that controls the tradeoff between
|
|
116
|
+
encoding encoding speed and compression (output size). Valid on the encoder (commonly
|
|
117
|
+
a string: "fast", "medium", "slow"). Defaults to None
|
|
118
|
+
(which will use encoder's default).
|
|
119
|
+
See :ref:`preset` for details.
|
|
120
|
+
extra_options (dict[str, Any], optional): A dictionary of additional
|
|
121
|
+
encoder options to pass, e.g. ``{"qp": 5, "tune": "film"}``.
|
|
122
|
+
See :ref:`extra_options` for details.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Tensor: The raw encoded bytes as 1D uint8 Tensor on CPU regardless of the device of the input frames.
|
|
126
|
+
"""
|
|
127
|
+
preset_value = str(preset) if isinstance(preset, int) else preset
|
|
128
|
+
return _core.encode_video_to_tensor(
|
|
129
|
+
frames=self._frames,
|
|
130
|
+
frame_rate=self._frame_rate,
|
|
131
|
+
format=format,
|
|
132
|
+
codec=codec,
|
|
133
|
+
pixel_format=pixel_format,
|
|
134
|
+
crf=crf,
|
|
135
|
+
preset=preset_value,
|
|
136
|
+
extra_options=[
|
|
137
|
+
str(x) for k, v in (extra_options or {}).items() for x in (k, v)
|
|
138
|
+
],
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def to_file_like(
|
|
142
|
+
self,
|
|
143
|
+
file_like,
|
|
144
|
+
format: str,
|
|
145
|
+
*,
|
|
146
|
+
codec: str | None = None,
|
|
147
|
+
pixel_format: str | None = None,
|
|
148
|
+
crf: int | float | None = None,
|
|
149
|
+
preset: str | int | None = None,
|
|
150
|
+
extra_options: dict[str, Any] | None = None,
|
|
151
|
+
) -> None:
|
|
152
|
+
"""Encode frames into a file-like object.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
file_like: A file-like object that supports ``write()`` and
|
|
156
|
+
``seek()`` methods, such as io.BytesIO(), an open file in binary
|
|
157
|
+
write mode, etc. Methods must have the following signature:
|
|
158
|
+
``write(data: bytes) -> int`` and ``seek(offset: int, whence:
|
|
159
|
+
int = 0) -> int``.
|
|
160
|
+
format (str): The container format of the encoded frames, e.g. "mp4", "mov",
|
|
161
|
+
"mkv", "avi", "webm", "flv", etc.
|
|
162
|
+
codec (str, optional): The codec to use for encoding (e.g., "libx264",
|
|
163
|
+
"h264"). If not specified, the default codec
|
|
164
|
+
for the container format will be used.
|
|
165
|
+
See :ref:`codec_selection` for details.
|
|
166
|
+
pixel_format (str, optional): The pixel format for encoding (e.g.,
|
|
167
|
+
"yuv420p", "yuv444p"). If not specified, uses codec's default format.
|
|
168
|
+
Must be left as ``None`` when encoding CUDA tensors.
|
|
169
|
+
See :ref:`pixel_format` for details.
|
|
170
|
+
crf (int or float, optional): Constant Rate Factor for encoding quality. Lower values
|
|
171
|
+
mean better quality. Valid range depends on the encoder (e.g. 0-51 for libx264).
|
|
172
|
+
Defaults to None (which will use encoder's default).
|
|
173
|
+
See :ref:`crf` for details.
|
|
174
|
+
preset (str or int, optional): Encoder option that controls the tradeoff between
|
|
175
|
+
encoding encoding speed and compression (output size). Valid on the encoder (commonly
|
|
176
|
+
a string: "fast", "medium", "slow"). Defaults to None
|
|
177
|
+
(which will use encoder's default).
|
|
178
|
+
See :ref:`preset` for details.
|
|
179
|
+
extra_options (dict[str, Any], optional): A dictionary of additional
|
|
180
|
+
encoder options to pass, e.g. ``{"qp": 5, "tune": "film"}``.
|
|
181
|
+
See :ref:`extra_options` for details.
|
|
182
|
+
"""
|
|
183
|
+
preset = str(preset) if isinstance(preset, int) else preset
|
|
184
|
+
_core.encode_video_to_file_like(
|
|
185
|
+
frames=self._frames,
|
|
186
|
+
frame_rate=self._frame_rate,
|
|
187
|
+
format=format,
|
|
188
|
+
file_like=file_like,
|
|
189
|
+
codec=codec,
|
|
190
|
+
pixel_format=pixel_format,
|
|
191
|
+
crf=crf,
|
|
192
|
+
preset=preset,
|
|
193
|
+
extra_options=[
|
|
194
|
+
str(x) for k, v in (extra_options or {}).items() for x in (k, v)
|
|
195
|
+
],
|
|
196
|
+
)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
|
|
3
|
+
from torchcodec import FrameBatch
|
|
4
|
+
|
|
5
|
+
_LIST_OF_INT_OR_FLOAT = list[int] | list[float]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _repeat_last_policy(
|
|
9
|
+
values: _LIST_OF_INT_OR_FLOAT, desired_len: int
|
|
10
|
+
) -> _LIST_OF_INT_OR_FLOAT:
|
|
11
|
+
# values = [1, 2, 3], desired_len = 5
|
|
12
|
+
# output = [1, 2, 3, 3, 3]
|
|
13
|
+
values += [values[-1]] * (desired_len - len(values))
|
|
14
|
+
return values
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _wrap_policy(
|
|
18
|
+
values: _LIST_OF_INT_OR_FLOAT, desired_len: int
|
|
19
|
+
) -> _LIST_OF_INT_OR_FLOAT:
|
|
20
|
+
# values = [1, 2, 3], desired_len = 5
|
|
21
|
+
# output = [1, 2, 3, 1, 2]
|
|
22
|
+
return (values * (desired_len // len(values) + 1))[:desired_len]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _error_policy(
|
|
26
|
+
frames_indices: _LIST_OF_INT_OR_FLOAT, desired_len: int
|
|
27
|
+
) -> _LIST_OF_INT_OR_FLOAT:
|
|
28
|
+
raise ValueError(
|
|
29
|
+
"You set the 'error' policy, and the sampler tried to decode a frame "
|
|
30
|
+
"that is beyond the number of frames in the video. "
|
|
31
|
+
"Try to leave sampling_range_end to its default value?"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
_POLICY_FUNCTION_TYPE = Callable[[_LIST_OF_INT_OR_FLOAT, int], _LIST_OF_INT_OR_FLOAT]
|
|
36
|
+
|
|
37
|
+
_POLICY_FUNCTIONS: dict[str, _POLICY_FUNCTION_TYPE] = {
|
|
38
|
+
"repeat_last": _repeat_last_policy,
|
|
39
|
+
"wrap": _wrap_policy,
|
|
40
|
+
"error": _error_policy,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _validate_common_params(*, decoder, num_frames_per_clip, policy):
|
|
45
|
+
if len(decoder) < 1:
|
|
46
|
+
raise ValueError(
|
|
47
|
+
f"Decoder must have at least one frame, found {len(decoder)} frames."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if num_frames_per_clip <= 0:
|
|
51
|
+
raise ValueError(
|
|
52
|
+
f"num_frames_per_clip ({num_frames_per_clip}) must be strictly positive"
|
|
53
|
+
)
|
|
54
|
+
if policy not in _POLICY_FUNCTIONS.keys():
|
|
55
|
+
raise ValueError(
|
|
56
|
+
f"Invalid policy ({policy}). Supported values are {_POLICY_FUNCTIONS.keys()}."
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _reshape_4d_framebatch_into_5d(
|
|
61
|
+
*,
|
|
62
|
+
frames: FrameBatch,
|
|
63
|
+
num_clips: int,
|
|
64
|
+
num_frames_per_clip: int,
|
|
65
|
+
) -> FrameBatch:
|
|
66
|
+
last_3_dims = frames.data.shape[-3:]
|
|
67
|
+
return FrameBatch(
|
|
68
|
+
data=frames.data.view(num_clips, num_frames_per_clip, *last_3_dims),
|
|
69
|
+
pts_seconds=frames.pts_seconds.view(num_clips, num_frames_per_clip),
|
|
70
|
+
duration_seconds=frames.duration_seconds.view(num_clips, num_frames_per_clip),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
_FRAMEBATCH_RETURN_DOCS = """
|
|
75
|
+
Returns:
|
|
76
|
+
FrameBatch:
|
|
77
|
+
The sampled :term:`clips`, as a 5D :class:`~torchcodec.FrameBatch`.
|
|
78
|
+
The shape of the ``data`` field is (``num_clips``,
|
|
79
|
+
``num_frames_per_clips``, ...) where ... is (H, W, C) or (C, H, W)
|
|
80
|
+
depending on the ``dimension_order`` parameter of
|
|
81
|
+
:class:`~torchcodec.decoders.VideoDecoder`. The shape of the
|
|
82
|
+
``pts_seconds`` and ``duration_seconds`` fields is (``num_clips``,
|
|
83
|
+
``num_frames_per_clips``).
|
|
84
|
+
"""
|