Open bugs181 opened 8 years ago
After a little more research, my hunch is that the issue lies within the Audio-Latency
header that the server sends during the RECORD request. With Apple products, it appears that it's the server's responsibility to look at the rtptime
property of the RTP-Info
header and adjust playback accordingly.
It appears you've already come to the same conclusion regarding your comment:
if (!req.getHeader('RTP-Info')) {
// it seems like iOS airplay does something else
The error I ran into earlier was actually pointing me in the right direction. There was an uncaptured setParameter
method which just so happens to include the rtptime
Here's the capture of that request:
{ 'rtp-info': 'rtptime=2972745305',
'content-length': '0',
'content-type': 'image/none',
cseq: '6',
'dacp-id': '3EA1CB210409B4E8',
'active-remote': '3043816175',
'user-agent': 'AirPlay/268.1' }
And here is an in-depth answer of how to calculate WHEN to start playing the audio. http://stackoverflow.com/a/21585663/1251309
From my understanding, there's a small formula to calculate a timestamp from when you can start playing the audio.
Tried my hand at implementing the formula myself but I'm missing something.
In rtspmethods.js
:
var setParameter = function(req, res) {
if (req.getHeader('Content-Type') == 'image/none') {
var rtpInfo = req.getHeader('rtp-info')
var rtptime = rtpInfo.split('rtptime=')[1]
if (rtptime) {
var calc = (((rtptime % 16000) / (16000 / 8000))) * 125 / 1000
setTimeout(function() {
rtspServer.external.emit('startStream', rtspServer.outputStream)
}, calc * 2)
}
}
And in server.js
server.on('startStream', function(stream) {
stream.pipe(speaker)
})
I believe the issue comes down to one or more of the following:
rtptime
from RTP-Info
headerI don't understand the AirPlay protocol well enough and have only been looking into the matter for less than 2 days.
More info Sync Packets:
Sync packets are sent once per second to the control port. They are used to correlate the RTP timestamps currently used in the audio stream to the NTP time used for clock synchronization.
Timing Packets:
Timing packets are used to synchronize a master clock for audio. This is useful for clock recovery and precise synchronization of several devices playing the same audio stream.
Similar issue from Mac 10.11 to Sonos speaker.
Seeing this on 10.11.5 with Node 6.7.0
But I am seeing delay in audio when using airsonos. Is it the same issue as this one?
@bugs181 How did you implement the change mentioned above into server.js? Do you have a copy you can share? I'm going to try and tackle the formula for the delay.
Trying to stream from a new AppleTV 4. A video delay of 1 to 3 seconds is apparent. Compared against another app (Airfoil Speakers) with no apparent delay.
Had to modify line 233 of
rtspmethods.js
in order to avoid a crash.Adding a small 2 second delay before piping to
speaker
can sometimes temporarily fix the issue. After a couple minutes there is however an apparent drift.