Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    NewUserHa
    @NewUserHa
    no. pyav has many streaming use cases as you can see on github issue tracker
    quantotto
    @quantotto
    Whatever works from ffmpeg cli will work through pyav as well. Just need to make sure correct options are supplied and, in some cases, things like pts / dts need to be set manually.
    NewUserHa
    @NewUserHa
    maybe pull from testsrc is using python's main thread??
    quantotto
    @quantotto
    @NewUserHa I don't think that this is the case of slow Python (thought I might be wrong). Most of the processing is happening in libav libraries (in C/C++). It is something related to logic of the graph.
    NewUserHa
    @NewUserHa
    the videoframe pulled from libav is in python's object form which is slow
    and change src rate from 30 to 2 solving the issue may also indicate the reason?
    quantotto
    @quantotto
    @NewUserHa did rate change solve the issue? I saw that localtime lagging even more, but it could be that I didn't run it properly. I didn't have too much time to invest in it
    NewUserHa
    @NewUserHa
    heard you said change src rate from 30 to 2 solving the issue..
    will try to change it to 60 fps later.
    quantotto
    @quantotto
    @NewUserHa what i said: "If you change rate to 2 from 30 everything becomes even slower."
    NewUserHa
    @NewUserHa
    the localtime difference is different with pts difference, also different with frame.
    but from the frame number, the video does delay, but not that much as localtime showed. and pts slower than other's changes is also weired
    quantotto
    @quantotto
    @nitanmarcel the following works fine for me and not reaching end of file. It continuously reads packets from the stream. I had to stop it with CTRL-C; otherwise, it runs endlessly.
    >>> import av
    >>> a = av.open("https://stream.live.vc.bbcmedia.co.uk/bbc_radio_one")
    >>> s = a.streams.audio[0]
    >>> s
    <av.AudioStream #0 mp3float at 48000Hz, stereo, fltp at 0x1c4ce7a9940>
    >>> for pkt in a.demux(s):
    ...     print(pkt.pts)
    ...
    0
    338688
    677376
    1016064
    1354752
    1693440
    2032128
    2370816
    2709504
    ...
    Nitan Alexandru Marcel
    @nitanmarcel
    Thanks I'll try to experiment with that. One last question tho: Calling a.close() will stop the outgoing process?
    quantotto
    @quantotto
    @nitanmarcel a.close() closes file object that you read / write or network connection of streaming. Not sure what you mean by "outgoing process"
    Nitan Alexandru Marcel
    @nitanmarcel
    Ah thanks. I just want to stop the stream without having to ctrl+c
    quantotto
    @quantotto
    You can also break the loop when needed and stop reading packets from demux generator and then call close.
    Nitan Alexandru Marcel
    @nitanmarcel
    @quantotto so I started with something like this:
    async def _start_av(self): input_ = await run_in_executor(av.open, self.url, options={"format": "s16le", "acodec": "pcm_s16le", "ac": "2", "ar": "48k"}) for frame in input_.decode(): if frame: self._fifo.write(frame)
    wait

    So I've started with something like this:

    self._fifo = av.AudioFifo(format="s16le")
    
    def _start_av(self):
    input_ = av.open(self.url, options={"format": "s16le", "acodec": "pcm_s16le", "ac": "2", "ar": "48k"})
    for frame in input_decode():
        if frame:
            self._fifo.write(frame)
    
    def read(self, length):
        data = self._fifo.read(length)
        if data:
            data = data.to_ndarray().tobytes()
        return data # returns the data to the library

    But I have a small problem, the data received from the AudioFifo is bigger than the one requested

    or wait, maybe I'm getting the AudioFifo wrong
    Nitan Alexandru Marcel
    @nitanmarcel
    Wait, can in this example self._fifo be any object that has a write method similar to bytesio?
    quantotto
    @quantotto
    @nitanmarcel I am not sure I have the full context of how you obtain length, who calls read etc.
    Nitan Alexandru Marcel
    @nitanmarcel
    @quantotto it's a library that requires raw data in pcm 16bit 48k so the length is returned by the library and it indicates the exact length of bytes it needs to properly play.
    The read function is called every time by the library when a set of bytes are played
    And what I'm looking for is to use pyav to format any audio from an url (it can also be an ytdl url) to the required format and feed it to the library and all of this while keeping the memory clean.
    quantotto
    @quantotto
    @nitanmarcel I read about AudioFifo in docs and it could be that you use length incorrectly. AudioFifo.read method expects number of samples to read. You mentioned that the library supplying length expects length amount of bytes. With Audio, amount of samples is not equal to amount of bytes. For example, in your case, pcm_s16le means that each sample is 16 bit little endian and this is 2 bytes per sample. If library is indeed supplying to you number of bytes it expects, you need to read length / 2 number of samples. With that, I hope the library is aligned with audio realities and asks for number of samples.
    Nitan Alexandru Marcel
    @nitanmarcel
    Thanks @quantotto I'll try this. Btw I can't use AudioFifo with av.open(AudioFifo)? I tried that and it says that NoneType has no attribute sample_rate even tho AudioFifo was initiated
    Also is the conversion right? Because I just did length / 8 (8 being the bytes/sample) and even tho the length of bytes was correct the sound came distorted with white noises (hints to a bad number of bytes or bad format)
    Nitan Alexandru Marcel
    @nitanmarcel
    @quantotto done I did it
    ~~~async def main():
    async with client:
        fifo: av.AudioFifo = av.AudioFifo(format="s16le")
        resampler: av.AudioResampler = av.AudioResampler(
            format="s16", layout="stereo", rate=48000)
    
        def on_played_data(_, length):
            data = fifo.read(length / 4)
            if data:
                data = data.to_ndarray().tobytes()
            return data
    
        group_call_factory = GroupCallFactory(client, CLIENT_TYPE)
        group_call = group_call_factory.get_raw_group_call(
            on_played_data=on_played_data)
    
        await group_call.start(PEER)
        while not group_call.is_connected:
            await asyncio.sleep(1)
    
        input_ = av.open(STREAM)
        for frame in input_.decode():
            if frame:
                print(frame)
                frame = resampler.resample(frame)
                fifo.write(frame)
    
        await client.run_until_disconnected()~~~
    This is the working code for me
    Nitan Alexandru Marcel
    @nitanmarcel
    Thanks to everyone who put up with me and gave me tips. Now I just need to know about the AudioFifo. If I have the radio stream and let it run for a long time will the stored bytes increase the ram usage or once they are read they are removed?
    Because if not I might need to create my own implementation
    quantotto
    @quantotto
    if you are reading fast enough, memory shouldn't increase indefinitely.
    Nitan Alexandru Marcel
    @nitanmarcel
    nice, thanks
    got a weird error when I'm using it from a file name
        _input = av.open(SOURCE, metadata_errors="ignore")
        for frame in _input.decode():
            fifo.write(frame)
    gives Invalid data found when processing input; last error log: [mp3float] Header missing
    quantotto
    @quantotto
    File format might be not supported by AV. Is it MP3? Try checking if it is identified correctly by ffmpeg: ffprobe <filename>
    Nitan Alexandru Marcel
    @nitanmarcel
    it is
    Nitan Alexandru Marcel
    @nitanmarcel
    Another error now: Input frame pts 487305 != expected 0; fix or set to None.
    but this in resampler
    quantotto
    @quantotto
    @nitanmarcel sometimes decoders have issues in the middle of the stream. Some are safe to ignore, some not. Try to run some re-encoding through command line with ffmpeg. I bet it will have those errors too. I don't think it has anything to do with PyAV library.
    Nitan Alexandru Marcel
    @nitanmarcel
    @quantotto The commandline worked: ffmpeg -i input.mp3 -f s16le -acodec pcm_s16le output.raw
    Nitan Alexandru Marcel
    @nitanmarcel
    oh I fixed it by setting pts to None
    Nitan Alexandru Marcel
    @nitanmarcel
    Could anyone point me to the part in the ffmpeg code where it handles the command line input? Thanks.
    marcelnitan
    @marcelnitan:envs.net
    [m]
    Nice, I can use matrix instead of the bad gitter app