示例#1
0
    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)
示例#2
0
    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)
示例#3
0
 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]
示例#4
0
    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)
示例#5
0
    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
示例#6
0
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
示例#7
0
    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)
示例#8
0
 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))
示例#9
0
 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))
示例#10
0
 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
示例#11
0
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
示例#12
0
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
示例#13
0
    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.')
示例#14
0
    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)
示例#15
0
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
示例#16
0
    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)
示例#17
0
    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.'
        )
示例#18
0
    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]
示例#19
0
 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
示例#20
0
 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)
示例#21
0
 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)
示例#22
0
 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)
示例#23
0
 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)
示例#24
0
    async def recv(self):
        if self.readyState != "live":
            raise MediaStreamError

        data = await self.__queue.get()
        if not data:
            self.stop()
            raise MediaStreamError

        try:
            indata, _ = data
            frame = AudioFrame.from_ndarray(indata.reshape(indata.shape[::-1]),
                                            format='s16',
                                            layout='mono')

            sample_rate = indata.shape[0]

            if hasattr(self, "_timestamp"):
                samples = int((time.time() - self._start) * sample_rate)
                self._timestamp += samples
            else:
                self._start = time.time()
                self._timestamp = 0

            frame.pts = self._timestamp
            frame.sample_rate = sample_rate
            frame.time_base = fractions.Fraction(1, sample_rate)
            return frame
        except:
            Logger.exception('Audio:')

            self.stop()
            raise MediaStreamError
示例#25
0
 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)
示例#26
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]
示例#27
0
    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 Exception("media stream error")  # MediaStreamError

        sample_rate = 16000  # 8000
        samples = int(AUDIO_PTIME * sample_rate)
        # logger.info("WTF!!")
        if hasattr(self, "_timestamp"):
            self._timestamp += samples
            wait = self._start + (self._timestamp / sample_rate) - time.time()
            # logger.info("wating... {0}".format(wait))
            await asyncio.sleep(wait)
        else:
            self._start = time.time()
            self._timestamp = 0

        # await asyncio.sleep(0.01)
        try:

            # data = sounddevice.rec(frames=samples, samplerate=sample_rate, channels=1, dtype='int16', blocking=True)
            data, overflowed = self.stream.read(frames=samples)
            #print("data", data)
            #print("data", data.shape)
            #data = np.zeros((2,1152), dtype='int16')
            #logger.info(data)

            # frameb = AudioFrame(format="s16", layout="mono", samples=samples)
            # logger.info('*****************************')
            # alt_data = frameb.to_ndarray()
            # logger.info(alt_data)
            # logger.info(alt_data.shape)
            # logger.info('-----------------')
            fixed_data = np.swapaxes(data, 0, 1)
            #print(fixed_data.shape)
            #print(fixed_data.dtype)
            #print(data.dtype)
            #print(fixed_data.dtype)
            frame = AudioFrame.from_ndarray(
                fixed_data, layout="mono",
                format='s16')  # layout="stereo", format='s32') # s16
            #for p in frame.planes:
            #    p.update(data.tobytes()) #bytes(p.buffer_size))
            # logger.info(frame.planes)
            # logger.info("\n!!!!!!!!!!!")
            frame.pts = self._timestamp
            frame.sample_rate = sample_rate
            frame.time_base = fractions.Fraction(1, sample_rate)
        except Exception as exc:
            print(exc)
            logger.exception(exc)
        return frame
示例#28
0
    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)
示例#29
0
    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)
示例#30
0
    def write_raw(self, data: av.AudioFrame):
        if self.container is None:
            self.container = av.open(self.path, 'w')
            self.stream = self.container.add_stream('aac',
                                                    rate=self.frame_rate)
            logger.debug(f"Opened stream: {self.path}")

        data.pts = None

        for packet in self.stream.encode(data):
            self.container.mux(packet)
示例#31
0
    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)
示例#32
0
 def test_ndarray_u8(self):
     layouts = [
         ('u8', 'mono', 'u1', (1, 160)),
         ('u8', 'stereo', 'u1', (1, 320)),
         ('u8p', 'mono', 'u1', (1, 160)),
         ('u8p', 'stereo', 'u1', (2, 160)),
     ]
     for format, layout, dtype, size in layouts:
         array = numpy.random.randint(0, 256, size=size, dtype=dtype)
         frame = AudioFrame.from_ndarray(array, format=format, layout=layout)
         self.assertEqual(frame.format.name, format)
         self.assertEqual(frame.layout.name, layout)
         self.assertEqual(frame.samples, 160)
         self.assertTrue((frame.to_ndarray() == array).all())
示例#33
0
    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)
示例#34
0
    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)
示例#35
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
示例#36
0
 def test_ndarray_dbl(self):
     layouts = [
         ('dbl', 'mono', '<f8', (1, 160)),
         ('dbl', 'stereo', '<f8', (1, 320)),
         ('dblp', 'mono', '<f8', (1, 160)),
         ('dblp', 'stereo', '<f8', (2, 160)),
     ]
     for format, layout, dtype, size in layouts:
         array = numpy.ndarray(shape=size, dtype=dtype)
         for i in range(size[0]):
             array[i][:] = numpy.random.rand(size[1])
         frame = AudioFrame.from_ndarray(array, format=format, layout=layout)
         self.assertEqual(frame.format.name, format)
         self.assertEqual(frame.layout.name, layout)
         self.assertEqual(frame.samples, 160)
         self.assertTrue((frame.to_ndarray() == array).all())
示例#37
0
 def test_ndarray_u8(self):
     layouts = [
         ("u8", "mono", "u1", (1, 160)),
         ("u8", "stereo", "u1", (1, 320)),
         ("u8p", "mono", "u1", (1, 160)),
         ("u8p", "stereo", "u1", (2, 160)),
     ]
     for format, layout, dtype, size in layouts:
         array = numpy.random.randint(0, 256, size=size, dtype=dtype)
         frame = AudioFrame.from_ndarray(array,
                                         format=format,
                                         layout=layout)
         self.assertEqual(frame.format.name, format)
         self.assertEqual(frame.layout.name, layout)
         self.assertEqual(frame.samples, 160)
         self.assertNdarraysEqual(frame.to_ndarray(), array)
示例#38
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)
示例#39
0
文件: tracks.py 项目: dkumor/rtcbot
    async def recv(self):
        if self._startTime is None and self._startedCallback is not None:
            self._startedCallback()
        try:
            data = await self._audioSubscription.get()
        except SubscriptionClosed:
            self._log.debug(
                "Audio track finished. raising MediaStreamError to shut down connection"
            )
            self.stop()
            raise MediaStreamError
        except:
            self._log.exception("Got unknown error. Crashing video stream")
            self.stop()
            raise MediaStreamError

        # self._log.exception("FAIL")

        # self._log.info("GOT AUDIO %d,%d", data.shape[0], data.shape[1])

        # self._log.info("Creating FRAME")
        # https://trac.ffmpeg.org/wiki/audio%20types
        # https://github.com/mikeboers/PyAV/blob/develop/av/audio/frame.pyx
        # https://ffmpeg.org/doxygen/3.0/group__channel__mask__c.html
        #
        # It looks like at the time of writing, audio samples are only accepted as s16,
        # and not as float (flt) in aiortc. We therefore use s16 as format instead of flt,
        # and convert the data:
        # https://github.com/jlaine/aiortc/blob/master/aiortc/codecs/opus.py
        # We therefore force a conversion to 16 bit integer:

        data = (np.clip(data, -1, 1) * 32768).astype(np.int16)

        new_frame = AudioFrame.from_ndarray(
            data, format="s16", layout=str(data.shape[0]) + "c"
        )

        # Use the sample rate for the base clock
        new_frame.sample_rate = self._sampleRate
        new_frame.time_base = fractions.Fraction(1, self._sampleRate)

        if self._startTime is None:
            self._startTime = time.time()
        # We need to compute the timestamp of the frame.
        # We want to handle audio without skips, where we simply increase the clock according
        # to the samples. However, sometimes the data might come in a bit late, which would
        # mean that we still want to get it correctly.
        # However, we have no guarantee that the data is actually coming without skipped
        # points. We try to detect if the data coming seems to be way behind the current
        # perfect timestamp, and in that situation, we can decide to skip forward if canSkip is True
        # https://en.wikipedia.org/wiki/Presentation_timestamp
        # Since our clock rate is simply our sample rate, the timestamp is the number of samples
        # we should have seen so far

        new_frame.pts = self._sampleNumber
        self._sampleNumber += data.shape[1]

        perfectSampleNumber = (
            int((time.time() - self._startTime) * self._sampleRate) + data.shape[1]
        )
        # print(perfectSampleNumber - self._sampleNumber)
        if self._canSkip:

            if perfectSampleNumber - self._sampleRate * 1 > self._sampleNumber:
                # The audio is over 1 second behind where it is supposed to be.
                # Adjust the sample number to the ``corrected" version
                self._log.warn(
                    "Received audio is over 1 second behind optimal timestamp! Skipping audio forward! Use canSkip=False to disable this correction"
                )
                new_frame.pts = perfectSampleNumber - data.shape[1]

        if perfectSampleNumber + self._sampleRate * 2 < self._sampleNumber:
            # If the audio stream is over 2 seconds ahead, we wait 1 second before continuing
            self._log.debug("Stream is over 2 seconds ahead. Sleeping for 1 second.")
            await asyncio.sleep(1)

        # print("\n\nSENDING DATA", new_frame, new_frame.time_base)
        self._log.debug("Writing frame %s", new_frame)
        return new_frame
示例#40
0
 def test_basic_to_ndarray(self):
     frame = AudioFrame(format='s16p', layout='stereo', samples=160)
     array = frame.to_ndarray()
     self.assertEqual(array.dtype, '<i2')
     self.assertEqual(array.shape, (2, 160))
示例#41
0
 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))