openairplay / airplay2-receiver

AirPlay 2 Receiver - Python implementation
2.15k stars 134 forks source link

Lock av version to 8.1.0 #72

Closed m3brown closed 2 years ago

m3brown commented 2 years ago

This PR resolves #71.

On my machine (M1 Mac / ARM64), av>=9.0.0 has weird issues where the package is installed in a directory that is not part of the sys.path, resulting in a ModuleNotFound error.

Locking the version to the last version before 9.0.0 appears to resolve the issue.

Odds and ends

It may also be possible to resolve this issue by removing --no-cache-dir in the Dockerfile. I can't explain why that flag causes issues with av.

After making the change in this PR against an older commit (1bb03ca0bb0f8be96658aad936061e928b6fd77f), I was still having issues when running import av that appear to be unique to ARM... but I don't have that issue against master.

@Shjba @oppermax @FlixFlix if you're able to test out this branch, I'd appreciate it!

TheSpookyCat commented 2 years ago

While testing I was having issues getting audio to play on Windows and even experienced the following exception

Exception in thread Thread-2 (play):
Traceback (most recent call last):
  File "Python310\lib\threading.py", line 1009, in _bootstrap_inner 
    self.run()
  File "Python310\lib\threading.py", line 946, in run
    self._target(*self._args, **self._kwargs)
  File "airplay2-receiver\ap2\connections\audio.py", line 912, in play       
    audio = self.process(rtp)
  File "airplay2-receiver\ap2\connections\audio.py", line 572, in process    
    return frame.planes[0].to_bytes()
AttributeError: 'list' object has no attribute 'planes'
Exception in thread Thread-1 (serve):
Traceback (most recent call last):
  File "Python310\lib\threading.py", line 1009, in _bootstrap_inner 
    self.run()
  File "Python310\lib\threading.py", line 946, in run
    self._target(*self._args, **self._kwargs)
  File "airplay2-receiver\ap2\connections\audio.py", line 933, in serve      
    while playerconn.poll():
  File "Python310\lib\multiprocessing\connection.py", line 262, in p
oll
    return self._poll(timeout)
  File "Python310\lib\multiprocessing\connection.py", line 333, in _
poll
    _winapi.PeekNamedPipe(self._handle)[0] != 0):
BrokenPipeError: [WinError 109] The pipe has been ended

Downgrading to av==8.1.0 resolved this exception & the audio issue, so I can only assume there's been a breaking change with the av library since the 9.X.Y releases. Since 8.1.0 fixes all of these problems I'm going to merge until we can figure out a better fix.

Xhichn commented 1 year ago

It seems like the noise issue is related to frame resample. The resampler has been modified since PyAV version 9.0.0, which would generate extra zeros to the end of the frame and change the bytes length of that frame.

I run the airplay2-receiver on my Windows laptop, and use Apple Music on my iPhone to test.

When the installed av version is 8.1.0, the bytes length of the resampled frame is 4096, while at version 10.0.0, the bytes length increases to 4224. I check the length using these codes:

self.audio_screen_logger.debug(frame[0].planes[0])

and the output with lastest PyAV:

[AudioBuffered]: <av.AudioPlane 4224 bytes; buffer_ptr=0x1fee2a50740; at 0x1fee2d76680>

Assumed that all the extra bytes are zeros, then I try to modify the return of function process in audio.py (at nearly line 574), it sounds the same as using av 8.1.0 to me.

return bytes(frame[0].planes[0])[:4096]

Here are what I read from PyAV respository issues: https://github.com/PyAV-Org/PyAV/issues/977