forked from meta-pytorch/torchcodec
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_audio_encoder.py
More file actions
157 lines (142 loc) · 6.33 KB
/
Copy path_audio_encoder.py
File metadata and controls
157 lines (142 loc) · 6.33 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
from pathlib import Path
import torch
from torch import Tensor
from torchcodec import _core
class AudioEncoder:
"""A single-stream audio encoder.
.. note::
This is a convenience class for simple, one-shot audio encoding. For
multi-stream encoding (e.g. video + audio), incremental encoding, or
encoding multiple audio streams, use
:class:`~torchcodec.encoders.Encoder` instead. See
:ref:`sphx_glr_generated_examples_encoding_multi_stream_encoding.py` for
a tutorial.
Args:
samples (``torch.Tensor``): The samples to encode. This must be a 2D
tensor of shape ``(num_channels, num_samples)``, or a 1D tensor in
which case ``num_channels = 1`` is assumed. Values must be float
values in ``[-1, 1]``.
sample_rate (int): The sample rate of the **input** ``samples``. The
sample rate of the encoded output can be specified using the
encoding methods (``to_file``, etc.).
"""
def __init__(self, samples: Tensor, *, sample_rate: int):
torch._C._log_api_usage_once("torchcodec.encoders.AudioEncoder")
# Some of these checks are also done in C++: it's OK, they're cheap, and
# doing them here allows to surface them when the AudioEncoder is
# instantiated, rather than later when the encoding methods are called.
if not isinstance(samples, Tensor):
raise ValueError(
f"Expected samples to be a Tensor, got {type(samples) = }."
)
if samples.ndim == 1:
# make it 2D and assume 1 channel
samples = torch.unsqueeze(samples, 0)
if samples.ndim != 2:
raise ValueError(f"Expected 1D or 2D samples, got {samples.shape = }.")
if samples.dtype != torch.float32:
raise ValueError(f"Expected float32 samples, got {samples.dtype = }.")
if sample_rate <= 0:
raise ValueError(f"{sample_rate = } must be > 0.")
self._samples = samples
self._sample_rate = sample_rate
def to_file(
self,
dest: str | Path,
*,
bit_rate: int | None = None,
num_channels: int | None = None,
sample_rate: int | None = None,
) -> None:
"""Encode samples into a file.
Args:
dest (str or ``pathlib.Path``): The path to the output file, e.g.
``audio.mp3``. The extension of the file determines the audio
format and container.
bit_rate (int, optional): The output bit rate. Encoders typically
support a finite set of bit rate values, so ``bit_rate`` will be
matched to one of those supported values. The default is chosen
by FFmpeg.
num_channels (int, optional): The number of channels of the encoded
output samples. By default, the number of channels of the input
``samples`` is used.
sample_rate (int, optional): The sample rate of the encoded output.
By default, the sample rate of the input ``samples`` is used.
"""
_core.encode_audio_to_file(
samples=self._samples,
sample_rate=self._sample_rate,
filename=str(dest),
bit_rate=bit_rate,
num_channels=num_channels,
desired_sample_rate=sample_rate,
)
def to_tensor(
self,
format: str,
*,
bit_rate: int | None = None,
num_channels: int | None = None,
sample_rate: int | None = None,
) -> Tensor:
"""Encode samples into raw bytes, as a 1D uint8 Tensor.
Args:
format (str): The format of the encoded samples, e.g. "mp3", "wav"
or "flac".
bit_rate (int, optional): The output bit rate. Encoders typically
support a finite set of bit rate values, so ``bit_rate`` will be
matched to one of those supported values. The default is chosen
by FFmpeg.
num_channels (int, optional): The number of channels of the encoded
output samples. By default, the number of channels of the input
``samples`` is used.
sample_rate (int, optional): The sample rate of the encoded output.
By default, the sample rate of the input ``samples`` is used.
Returns:
Tensor: The raw encoded bytes as 1D uint8 Tensor.
"""
return _core.encode_audio_to_tensor(
samples=self._samples,
sample_rate=self._sample_rate,
format=format,
bit_rate=bit_rate,
num_channels=num_channels,
desired_sample_rate=sample_rate,
)
def to_file_like(
self,
file_like,
format: str,
*,
bit_rate: int | None = None,
num_channels: int | None = None,
sample_rate: int | None = None,
) -> None:
"""Encode samples into a file-like object.
Args:
file_like: A file-like object that supports ``write()`` and
``seek()`` methods, such as io.BytesIO(), an open file in binary
write mode, etc. Methods must have the following signature:
``write(data: bytes) -> int`` and ``seek(offset: int, whence:
int = 0) -> int``.
format (str): The format of the encoded samples, e.g. "mp3", "wav"
or "flac".
bit_rate (int, optional): The output bit rate. Encoders typically
support a finite set of bit rate values, so ``bit_rate`` will be
matched to one of those supported values. The default is chosen
by FFmpeg.
num_channels (int, optional): The number of channels of the encoded
output samples. By default, the number of channels of the input
``samples`` is used.
sample_rate (int, optional): The sample rate of the encoded output.
By default, the sample rate of the input ``samples`` is used.
"""
_core.encode_audio_to_file_like(
samples=self._samples,
sample_rate=self._sample_rate,
format=format,
file_like=file_like,
bit_rate=bit_rate,
num_channels=num_channels,
desired_sample_rate=sample_rate,
)