I have a navidrome server installed on Synology NAS.
I would like to have symphonium stream original files when playing and storing an opus 320 kb for offline rolling cache with automatic rules.
I did setup automatic rules or even when I do it manually I get retries and there is always error “Empty Downloaded File”.
The logs from Navidrome show
time=“2026-03-17T22:24:54+01:00” level=info msg=“Streaming file” artist=Metallica bitRate=320 cached=false format=opus originalBitRate=1012 originalFormat=flac requestId=szynka2/MKD1lxh5E8-000048 title=“The House Jack Built” transcoding=true user=marek
time=“2026-03-17T22:25:04+01:00” level=info msg=“Streaming file” artist=Metallica bitRate=320 cached=false format=opus originalBitRate=1012 originalFormat=flac requestId=szynka2/MKD1lxh5E8-000051 title=“The House Jack Built” transcoding=true user=marek
I will use the app to share the logs.
If in the quality of offline I select original I do get files. For faveorites I have set original quality and those do get downloaded and put in permanent cache
Setup Navidrome transcoding setting for opus audiot to 320.
In symphonium go to a a track select the 3 dots and click add to cache.
I the next screen select Transcoding 320 kbps, select add to rolling cache.
Click add, go to settings manage offline files and look at the download queue and see the track is trying to be downloaded and after couple of tries it will show error "Empty Downloaded File (Hex number)/true
Subsonic endpoints (stream, download, getTranscodeStream) now return a Subsonic error response when transcoding produces 0 bytes or io.Copy fails
Don’t do that, while I do have security for 0 bytes, if you return json data as the media data I have no way to know, nor ffmpeg or Chromecast or everything.
That part of Subsonic API was always absurd and LMS now properly returns http errors for an endpoint that is not consumed by Subsonic clients but audio renderers.
If you can’t return an http error, 0 is better for Symfonium to not cache invalid data without user errors and making users life harder.
From my perspective - if I had access to logs from symfonium or the error on the file would say no data received from server then I would look in navidrome and would not ask here. On the other hand if navidrome would report the error in the info logs I would also figure this out without external help. Just my 2 cents.
The description in the PR is wrong (I’ll fix it). The actual implementation returns Subsonic errors for the old endpoints (stream and downlaod), but proper http errors in getTranscodeStream.
Yeah but that’s what it should not do. An app that downloads a media to a file, will not read the content of the file to see if there’s some json in it or the actual media content.
As I said that part of the API was dumb the endpoint is consumed by things that expect raw content and can’t analyse json message with 200 code.
While Symfonium will use the new endpoints so won’t be impacted, any other client trying to offline cache the media with transcoding will cache the json and never know there’s an error.
We can suggest it’s better, but we can’t really enforce that anyway.
And yes it’s what most already do, but since you are touching it, it’s the perfect timing to not do it anymore
Debugging this user would have been insanely more complicated if you did return the json it would not have been detected, just random playback errors after trying to play the json file.
Returning 0 bytes and no error message was always wrong. That’s what I’m trying to fix here.
With my changes, it will return a response with generic error 0 and “transcoding failed: empty output” message.
And the actual issue with ffmpeg will be shown in Navidrome logs.
IMO, not really: you’d see the “transcoding failed: empty output” and you’d just ask them to check the server’s log, right? So I’d argue this is better for debugging
Anyway, I don’t feel comfortable changing this without documenting it. It would also affect GetCoverArt, GetAvatar and a few other endpoints that should return raw data. This should be discussed with the larger OpenSubsonic group.
That’s the whole point No it would not be seen at all.
When you download something and the endpoint returns 200 you take the bytes and write them to the target file. You do not read a couple of byte in memory, see if it’s a json or not and then write your memory cache then resume the download to the target file. So what all clients do is caching a media file thinking it’s ok while it’s just a small json data.
Same when you you cast remote device can say they can’t connect to endpoints, but they can’t say hey I get json, they will just fail with random can’t play error.
Anyway yes the logs on Navidrome will help, and do not change if you do not think it’s useful, but no returning a json does not help debugging client side at all.
Good point! I reverted it to returning status 200 with 0 bytes as it was before, while keeping the new logs in place. In GetTranscodeStream it returns a proper 500 error.
Anyway, I still think it is worth to open this discussion in the OS forum.
EDIT: Should we amend the transcoding extension to say that servers that implement it should always return a transcodeParams in getTranscodeDecision, and clients should always use getTranscodeStream? This would avoid reliance on the broken stream endpoint for new clients (and old ones that are willing to modernize)
We can discuss on OS yes, but as said it’s hard to enforce that late, adding an extension would not bring much to the table either. So if a simple should in the docs works for you then why not, but I don’t think we can get more without endless complicated discussions
For the transcoding endpoint that would be strange in many ways to send an obscure transcodeParam to a transcode endpoint to get a non transcoded stream. Makes it hard to what will happen in the end.
Maybe we can add a parameter to say don’t actually transcode (similar to the format=raw concept of the OG), no idea for naming right now but you get the idea.