-
Notifications
You must be signed in to change notification settings - Fork 257
[documentation] streaming/downloading track too slow makes gvs server close connection early #548
Comments
I've repeated your tests with the same song and the same (and even lower rate limits) 10-12 times without an issue. Is this something that happens occasionally or regularly in your testing? |
Yes I'm 100% able to reprod it. At 50K, transfer closes at 90%, at 30K at 84% and at 5K at 75% (note that for this last case we are way past the track duration, which makes this issue very weird). I can reprod this issue with non curl download code (with specific hardware streaming instead at a slow rate) and I observe the same issue (ECONNRESET). On a longer track, cut happens later: for example downloading @ 30K track T7gorf5c4iu7jwb7dk3ezzgnfzy whose duration is 7:02, it cuts at 94%. And on a 1:10 track @ 30K it cuts at 65%. So the shorter the track, the earlier it cut. Summary of download capped at 30Kb/s: Track / Duration / Cut at The percentage at which it cuts is repeatable with a variation possible of a few percents. Also I know this issue does not happen only on my system as I got user reports of it in the form 'playback sometimes stops xx seconds before then end on hardware yy'. Here's the verbose output for track @50k, so we can compare (I just edited the ip query field in the stream URL). Can you post yours with a successful download ? It could be interesting to compare the stream URL, in particular the value of the very obscure query fields most of which we probably have no idea what they are for: curl -v --limit-rate 50K 'https://r1---sn-n4g-cvqs.c.doc-0-0-sj.sj.googleusercontent.com/videoplayback?id=23aa28c6cc6153da&itag=25&source=skyjam&begin=0&upn=BewyAJZrqgU&ei=TSoDWcjGNOqw_gbsia7ADw&o=11552407006682955536&cmbypass=yes&ratebypass=yes&ip=xxx.xxx.xxx.xxx&ipbits=0&expire=1493379751&sparams=cmbypass,ei,expire,id,ip,ipbits,itag,mm,mn,ms,mv,o,pl,ratebypass,source,upn&signature=5D8DFD45CA193ECCCA7F4760384CD4D3352CE136.6A3AE01B75C409C4BD53075395E981B5DCB20468&key=cms1&mm=31&mn=sn-n4g-cvqs&ms=au&mt=1493379327&mv=m&pl=23' > /dev/null
< HTTP/1.1 200 OK
|
I don't see anything different in the URL params that shouldn't be (certain hashes/ids). Nor do I see anything different or odd in curl's verbose output for these tests except that yours fail while all of mine succeed. Should have as many others run these tests to see what happens. |
Yes I'd be curious to know if others devs can reproduce it. |
I am seeing transfer errors at all speeds, definitely more at high speed (I have around 500 KBytes/S downloads). At high speed, I am seeing a timeout or connection error every few tracks: 4 errors in 16 downloads of the same two tracks in my short test. Actually I initially thought that I only had errors at high speed and that this was a limitation "feature". But I also saw an error at playing speed while doing tests today (one track timeout in 2 hours of playing, 28 downloads of the above tracks). I am in Paris, and my conclusion at this point is that Google Music is just unreliable in France... |
This issue is not a bug, but to document very particular behavior from google streaming servers (gvs) when not downloading/streaming at full speed.
You get the stream URL of a track using get_stream_url().
If you download this URL at full speed, no problem.
Now if you download it at a slower rate (for playback for example), the download may interrupt mid-way or at 70-90% of the download. Why is it so ?
It happens that gvs (the Google Server) interrupts the download unexpectedly if it deems that the client is downloading too slow. But it does so not in a super obvious way and it took me forever to figure out (hence this post). The problem is that it is very aggressive at doing so, and it may happen even if a client downloads at more than 40kb / sec (this is the minimum rate required for playback fo 320 Kbps mp3.
Here's an example capping the download at 50Kb/s. The URL is the one returned by
api.get_stream_url('Tsr37bkzlgcbg33iiuolkop6q3a'). This particular track is useful for testing as it is only 2 min 17sec long:
curl --limit-rate 50K 'https://r1---sn-n4g-cvqs.c.doc-0-0-sj.sj.googleusercontent.com/videoplayback?...' > /dev/null
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
90 5331k 90 4831k 0 0 51125 0 0:01:46 0:01:36 0:00:10 50319
curl: (56) SSLRead() return error -9806
here we can see we get a SSRead() error at 90% of the transfer. This is in fact the server closing the connection unexpectedly and the client getting ECONNRESET in recv, which can be seen better replacing https with http:
curl --limit-rate 50K 'http://r1---sn-n4g-cvqs.c.doc-0-0-sj.sj.googleusercontent.com/videoplayback?...' > /dev/null
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
90 5331k 90 4799k 0 0 51031 0 0:01:46 0:01:36 0:00:10 49519
curl: (56) Recv failure: Connection reset by peer
Here, ECONNRESET is clear, also at 90%.
So if you cannot control directly at which rate the client is streaming (for example if it is black box hardware), what can you do ?
The solution is to proxy the stream, decoupling reading from gvs and client reading.
The proxy reads the stream at full speed (or good speed, say > 100Kb/s) with maximum buffering (ideally full track length but it could be half of that) and the client reads the buffered stream at its own slower pace.
The text was updated successfully, but these errors were encountered: