def test_manual_s16_mono_constructor(self): frame = AudioFrame(format='s16', layout='mono', samples=160) self.assertEqual(frame.format.name, 's16') self.assertEqual(frame.layout.name, 'mono') self.assertEqual(len(frame.planes), 1) self.assertEqual(frame.planes[0].buffer_size, 320) self.assertEqual(frame.samples, 160)
async def recv(self) -> Frame: """ Receive the next :class:`~av.audio.frame.AudioFrame`. The base implementation just reads silence, subclass :class:`AudioStreamTrack` to provide a useful implementation. """ if self.readyState != "live": raise MediaStreamError sample_rate = 8000 samples = int(AUDIO_PTIME * sample_rate) if hasattr(self, "_timestamp"): self._timestamp += samples wait = self._start + (self._timestamp / sample_rate) - time.time() await asyncio.sleep(wait) else: self._start = time.time() self._timestamp = 0 frame = AudioFrame(format="s16", layout="mono", samples=samples) for p in frame.planes: p.update(bytes(p.buffer_size)) frame.pts = self._timestamp frame.sample_rate = sample_rate frame.time_base = fractions.Fraction(1, sample_rate) return frame
def test_manual_flt_mono_constructor(self): frame = AudioFrame(format="flt", layout="mono", samples=160) self.assertEqual(frame.format.name, "flt") self.assertEqual(frame.layout.name, "mono") self.assertEqual(len(frame.planes), 1) self.assertEqual(frame.planes[0].buffer_size, 640) self.assertEqual(frame.samples, 160)
def test_pts_missing_time_base(self): resampler = AudioResampler("s16", "mono", 44100) # resample one frame iframe = AudioFrame("s16", "stereo", 1024) iframe.sample_rate = 48000 iframe.pts = 0 oframes = resampler.resample(iframe) self.assertEqual(len(oframes), 1) oframe = oframes[0] self.assertEqual(oframe.pts, 0) self.assertEqual(oframe.time_base, Fraction(1, 44100)) self.assertEqual(oframe.sample_rate, 44100) # flush oframes = resampler.resample(None) self.assertEqual(len(oframes), 1) oframe = oframes[0] self.assertEqual(oframe.pts, 925) self.assertEqual(oframe.time_base, Fraction(1, 44100)) self.assertEqual(oframe.sample_rate, 44100) self.assertEqual(oframe.samples, 16)
def test_stream_index(self): output = av.open(self.sandboxed('output.mov'), 'w') vstream = output.add_stream('mpeg4', 24) vstream.pix_fmt = 'yuv420p' vstream.width = 320 vstream.height = 240 astream = output.add_stream('mp2', 48000) astream.channels = 2 astream.format = 's16' self.assertEqual(vstream.index, 0) self.assertEqual(astream.index, 1) vframe = VideoFrame(320, 240, 'yuv420p') vpacket = vstream.encode(vframe)[0] self.assertIs(vpacket.stream, vstream) self.assertEqual(vpacket.stream_index, 0) for i in range(10): aframe = AudioFrame('s16', 'stereo', samples=astream.frame_size) aframe.rate = 48000 apackets = astream.encode(aframe) if apackets: apacket = apackets[0] break self.assertIs(apacket.stream, astream) self.assertEqual(apacket.stream_index, 1)
def decode(self, encoded_frame: JitterFrame) -> List[Frame]: frame = AudioFrame(format="s16", layout="mono", samples=SAMPLES_PER_FRAME) frame.planes[0].update(self._convert(encoded_frame.data, SAMPLE_WIDTH)) frame.pts = encoded_frame.timestamp frame.sample_rate = SAMPLE_RATE frame.time_base = TIME_BASE return [frame]
def test_stream_index(self): with av.open(self.sandboxed("output.mov"), "w") as output: vstream = output.add_stream("mpeg4", 24) vstream.pix_fmt = "yuv420p" vstream.width = 320 vstream.height = 240 astream = output.add_stream("mp2", 48000) astream.channels = 2 astream.format = "s16" self.assertEqual(vstream.index, 0) self.assertEqual(astream.index, 1) vframe = VideoFrame(320, 240, "yuv420p") vpacket = vstream.encode(vframe)[0] self.assertIs(vpacket.stream, vstream) self.assertEqual(vpacket.stream_index, 0) for i in range(10): if astream.frame_size != 0: frame_size = astream.frame_size else: # decoder didn't indicate constant frame size frame_size = 1000 aframe = AudioFrame("s16", "stereo", samples=frame_size) aframe.rate = 48000 apackets = astream.encode(aframe) if apackets: apacket = apackets[0] break self.assertIs(apacket.stream, astream) self.assertEqual(apacket.stream_index, 1)
def test_manual_flt_stereo_constructor(self): frame = AudioFrame(format='flt', layout='stereo', samples=160) self.assertEqual(frame.format.name, 'flt') self.assertEqual(frame.layout.name, 'stereo') self.assertEqual(len(frame.planes), 1) self.assertEqual(frame.planes[0].buffer_size, 1280) self.assertEqual(frame.samples, 160)
def test_manual_s16_mono_constructor_align_8(self): frame = AudioFrame(format="s16", layout="mono", samples=159, align=8) self.assertEqual(frame.format.name, "s16") self.assertEqual(frame.layout.name, "mono") self.assertEqual(len(frame.planes), 1) self.assertEqual(frame.planes[0].buffer_size, 320) self.assertEqual(frame.samples, 159)
def test_manual_s16_stereo_constructor(self): frame = AudioFrame(format="s16", layout="stereo", samples=160) self.assertEqual(frame.format.name, "s16") self.assertEqual(frame.layout.name, "stereo") self.assertEqual(len(frame.planes), 1) self.assertEqual(frame.planes[0].buffer_size, 640) self.assertEqual(frame.samples, 160)
def generate_audio_frame(frame_num, input_format="s16", layout="stereo", sample_rate=44100, frame_size=1024): """ Generate audio frame representing part of the sinusoidal wave :param input_format: default: s16 :param layout: default: stereo :param sample_rate: default: 44100 :param frame_size: default: 1024 :param frame_num: frame number :return: audio frame for sinusoidal wave audio signal slice """ frame = AudioFrame(format=input_format, layout=layout, samples=frame_size) frame.sample_rate = sample_rate frame.pts = frame_num * frame_size for i in range(len(frame.layout.channels)): data = np.zeros(frame_size, dtype=format_dtypes[input_format]) for j in range(frame_size): data[j] = np.sin(2 * np.pi * (frame_num + j) * (i + 1) / float(frame_size)) frame.planes[i].update(data) return frame
def create_audio_frame(self, samples, pts, layout="mono", sample_rate=48000): frame = AudioFrame(format="s16", layout=layout, samples=samples) for p in frame.planes: p.update(bytes(p.buffer_size)) frame.pts = pts frame.sample_rate = sample_rate frame.time_base = fractions.Fraction(1, sample_rate) return frame
def test_ndarray_s16p_align_8(self): frame = AudioFrame(format="s16p", layout="stereo", samples=159, align=8) array = frame.to_ndarray() self.assertEqual(array.dtype, "i2") self.assertEqual(array.shape, (2, 159))
def test_ndarray_s16p_align_8(self): frame = AudioFrame(format='s16p', layout='stereo', samples=159, align=8) array = frame.to_ndarray() self.assertEqual(array.dtype, '<i2') self.assertEqual(array.shape, (2, 159))
def test_mismatched_input(self): """ Consecutive frames must have the same layout, sample format and sample rate. """ resampler = AudioResampler("s16", "mono", 44100) # resample one frame iframe = AudioFrame("s16", "stereo", 1024) iframe.sample_rate = 48000 resampler.resample(iframe) # resample another frame with a sample format iframe = AudioFrame("s16", "mono", 1024) iframe.sample_rate = 48000 with self.assertRaises(ValueError) as cm: resampler.resample(iframe) self.assertEqual(str(cm.exception), "Frame does not match AudioResampler setup.")
def test_identity_passthrough(self): # If we don't ask it to do anything, it won't. resampler = AudioResampler() iframe = AudioFrame('s16', 'stereo', 1024) oframe = resampler.resample(iframe) self.assertIs(iframe, oframe)
def test_matching_passthrough(self): # If the frames match, it won't do anything. resampler = AudioResampler('s16', 'stereo') iframe = AudioFrame('s16', 'stereo', 1024) oframe = resampler.resample(iframe) self.assertIs(iframe, oframe)
def generate_audio_frame(): """Generate a blank audio frame.""" from av import AudioFrame audio_frame = AudioFrame(format='dbl', layout='mono', samples=1024) # audio_bytes = b''.join(b'\x00\x00\x00\x00\x00\x00\x00\x00' # for i in range(0, 1024)) audio_bytes = b'\x00\x00\x00\x00\x00\x00\x00\x00' * 1024 audio_frame.planes[0].update(audio_bytes) audio_frame.sample_rate = AUDIO_SAMPLE_RATE audio_frame.time_base = Fraction(1, AUDIO_SAMPLE_RATE) return audio_frame
def create_audio_frame(sample_func, samples, pts, layout="mono", sample_rate=48000): frame = AudioFrame(format="s16", layout=layout, samples=samples) for p in frame.planes: buf = bytearray() for i in range(samples): sample = int(sample_func(i) * 32767) buf.extend(int.to_bytes(sample, 2, sys.byteorder, signed=True)) p.update(buf) frame.pts = pts frame.sample_rate = sample_rate frame.time_base = fractions.Fraction(1, sample_rate) return frame
def test_pts_missing_time_base(self): resampler = AudioResampler('s16', 'mono', 44100) iframe = AudioFrame('s16', 'stereo', 1024) iframe.sample_rate = 48000 iframe.pts = 0 oframe = resampler.resample(iframe) self.assertIs(oframe.pts, None) self.assertIs(oframe.time_base, None) self.assertEqual(oframe.sample_rate, 44100)
def test_basic_to_nd_array(self): frame = AudioFrame(format='s16p', layout='stereo', samples=160) with warnings.catch_warnings(record=True) as recorded: array = frame.to_nd_array() self.assertEqual(array.shape, (2, 160)) # check deprecation warning self.assertEqual(len(recorded), 1) self.assertEqual(recorded[0].category, AttributeRenamedWarning) self.assertEqual( str(recorded[0].message), 'AudioFrame.to_nd_array is deprecated; please use AudioFrame.to_ndarray.' )
def decode(self, encoded_frame): frame = AudioFrame(format='s16', layout='stereo', samples=SAMPLES_PER_FRAME) frame.pts = encoded_frame.timestamp frame.sample_rate = SAMPLE_RATE frame.time_base = TIME_BASE length = lib.opus_decode( self.decoder, encoded_frame.data, len(encoded_frame.data), ffi.cast('int16_t *', frame.planes[0].buffer_ptr), SAMPLES_PER_FRAME, 0) assert length == SAMPLES_PER_FRAME return [frame]
def create_audio_frames(self, layout, sample_rate, count): frames = [] timestamp = 0 samples_per_frame = int(AUDIO_PTIME * sample_rate) for i in range(count): frame = AudioFrame(format="s16", layout=layout, samples=samples_per_frame) for p in frame.planes: p.update(bytes(p.buffer_size)) frame.pts = timestamp frame.sample_rate = sample_rate frame.time_base = fractions.Fraction(1, sample_rate) frames.append(frame) timestamp += samples_per_frame return frames
def test_pts_assertion_same_rate(self): resampler = AudioResampler("s16", "mono") # resample one frame iframe = AudioFrame("s16", "stereo", 1024) iframe.sample_rate = 48000 iframe.time_base = "1/48000" iframe.pts = 0 oframes = resampler.resample(iframe) self.assertEqual(len(oframes), 1) oframe = oframes[0] self.assertEqual(oframe.pts, 0) self.assertEqual(oframe.time_base, iframe.time_base) self.assertEqual(oframe.sample_rate, iframe.sample_rate) self.assertEqual(oframe.samples, iframe.samples) # resample another frame iframe.pts = 1024 oframes = resampler.resample(iframe) self.assertEqual(len(oframes), 1) oframe = oframes[0] self.assertEqual(oframe.pts, 1024) self.assertEqual(oframe.time_base, iframe.time_base) self.assertEqual(oframe.sample_rate, iframe.sample_rate) self.assertEqual(oframe.samples, iframe.samples) # resample another frame with a pts gap, do not raise exception iframe.pts = 9999 oframes = resampler.resample(iframe) self.assertEqual(len(oframes), 1) oframe = oframes[0] self.assertEqual(oframe.pts, 9999) self.assertEqual(oframe.time_base, iframe.time_base) self.assertEqual(oframe.sample_rate, iframe.sample_rate) self.assertEqual(oframe.samples, iframe.samples) # flush oframes = resampler.resample(None) self.assertEqual(len(oframes), 0)
def decode(self, encoded_frame: JitterFrame) -> List[Frame]: frame = AudioFrame(format="s16", layout="stereo", samples=SAMPLES_PER_FRAME) frame.pts = encoded_frame.timestamp frame.sample_rate = SAMPLE_RATE frame.time_base = TIME_BASE length = lib.opus_decode( self.decoder, encoded_frame.data, len(encoded_frame.data), ffi.cast("int16_t *", frame.planes[0].buffer_ptr), SAMPLES_PER_FRAME, 0, ) assert length == SAMPLES_PER_FRAME return [frame]
def test_pts_assertion_new_rate(self): resampler = AudioResampler('s16', 'mono', 44100) iframe = AudioFrame('s16', 'stereo', 1024) iframe.sample_rate = 48000 iframe.time_base = '1/48000' iframe.pts = 0 oframe = resampler.resample(iframe) self.assertEqual(oframe.pts, 0) self.assertEqual(str(oframe.time_base), '1/44100') self.assertEqual(oframe.sample_rate, 44100) samples_out = resampler.samples_out self.assertTrue(samples_out > 0) iframe.pts = 1024 oframe = resampler.resample(iframe) self.assertEqual(oframe.pts, samples_out) self.assertEqual(str(oframe.time_base), '1/44100') self.assertEqual(oframe.sample_rate, 44100)
def test_identity_passthrough(self): """ If we don't ask it to do anything, it won't. """ resampler = AudioResampler() # resample one frame iframe = AudioFrame("s16", "stereo", 1024) oframes = resampler.resample(iframe) self.assertEqual(len(oframes), 1) self.assertIs(iframe, oframes[0]) # resample another frame iframe.pts = 1024 oframes = resampler.resample(iframe) self.assertEqual(len(oframes), 1) self.assertIs(iframe, oframes[0]) # flush oframes = resampler.resample(None) self.assertEqual(len(oframes), 0)
def test_pts_assertion_same_rate(self): resampler = AudioResampler('s16', 'mono') iframe = AudioFrame('s16', 'stereo', 1024) iframe.sample_rate = 48000 iframe.time_base = '1/48000' iframe.pts = 0 oframe = resampler.resample(iframe) self.assertEqual(oframe.pts, 0) self.assertEqual(oframe.time_base, iframe.time_base) self.assertEqual(oframe.sample_rate, iframe.sample_rate) iframe.pts = 1024 oframe = resampler.resample(iframe) self.assertEqual(oframe.pts, 1024) self.assertEqual(oframe.time_base, iframe.time_base) self.assertEqual(oframe.sample_rate, iframe.sample_rate) iframe.pts = 9999 self.assertRaises(ValueError, resampler.resample, iframe)
def test_matching_passthrough(self): """ If the frames match, it won't do anything. """ resampler = AudioResampler("s16", "stereo") # resample one frame iframe = AudioFrame("s16", "stereo", 1024) oframes = resampler.resample(iframe) self.assertEqual(len(oframes), 1) self.assertIs(iframe, oframes[0]) # resample another frame iframe.pts = 1024 oframes = resampler.resample(iframe) self.assertEqual(len(oframes), 1) self.assertIs(iframe, oframes[0]) # flush oframes = resampler.resample(None) self.assertEqual(len(oframes), 0)
async def recv(self): """ Receive the next :class:`~av.audio.frame.AudioFrame`. The base implementation just reads silence, subclass :class:`AudioStreamTrack` to provide a useful implementation. """ if self.readyState != 'live': raise MediaStreamError sample_rate = 8000 samples = int(AUDIO_PTIME * sample_rate) timestamp = getattr(self, '_timestamp', 0) self._timestamp = timestamp + samples await asyncio.sleep(AUDIO_PTIME) frame = AudioFrame(format='s16', layout='mono', samples=samples) for p in frame.planes: p.update(bytes(p.buffer_size)) frame.pts = timestamp frame.sample_rate = sample_rate frame.time_base = fractions.Fraction(1, sample_rate) return frame