Thank you for your reply. I have some new findings here.
This weekend, I retested the behavior with Gapless mode turned off. It still repeats a single track instead of properly advancing to the next one.
I tried performing the same test using Windows Media Player, and I was pleasantly surprised to find that it worked correctly. After capturing network traffic, I obtained the communication between WMP / Symfonium and my Xiaoai speaker. With the assistance of AI analysis, I arrived at the following conclusions. Could you please take a moment to review whether the AI’s conclusions are valuable? Since the current page does not support uploading pcap files, I have not attached the capture file. If you are interested in this issue and would like to see the original packet capture, I’d like send it to you separately via email.
DLNA Single-Track Loop Issue Analysis Report
Issue Description
- Windows Media Player: Correctly advances to the next track automatically
- Symfonium: Always loops the same track repeatedly
This report analyzes network packet captures of both applications controlling a Xiaomi AI Speaker (DLNA renderer) to identify the root cause of the single-track loop behavior in Symfonium.
Packet Capture Details
Test Environment
- Renderer: Xiaomi AI Speaker (192.168.1.108)
- Symfonium Device: SkyFucker (192.168.1.200)
- WMP Device: HASEE-PRO (192.168.1.110)
- Capture Files:
symfonium.pcap - Symfonium playback session
wmp.pcapng - Windows Media Player playback session
Test Procedure
Both captures were performed with the following workflow:
- Multiple songs added to the playlist
- Start playing the first song
- Manually seek to near the end of the first song (approximately 00:03:38 out of 00:03:55 duration)
- Allow the song to play to completion
- Wait for automatic transition to the next track
Analysis of Symfonium Behavior
Timeline of Events (from symfonium.pcap)
Initial Playback Setup
22:15:24.424 - Stop
22:15:24.472 - SetAVTransportURI (First track: "River Flows In You")
URI: https://navidrome.domain.com:443/rest/stream.view?id=2fcfb184...
Duration: 00:03:55
User Seeks Near End of Track
22:15:35.133 - Seek (Target: 00:03:38)
Track Transition Attempt
22:15:59.479 - Stop (First track playback completed)
22:15:59.517 - SetAVTransportURI (Second track: "Party Train")
URI: https://navidrome.domain.com:443/rest/stream.view?id=03a1afe8...
Duration: 00:03:22
22:16:01.765 - Play
Critical Observation: There is a 2.29 second gap between the Stop command (22:15:59.479) and the Play command (22:16:01.765).
Key Findings
1. Track Transition Method
Symfonium uses a “Stop → SetAVTransportURI → Play” sequence to switch tracks:
Stop current playback
↓ (\~38ms)
SetAVTransportURI (set next track URI)
↓ (\~2.25 seconds)
Play new track
2. Missing UPnP Standard Mechanism
Symfonium does NOT use the SetNextAVTransportURI action, which is the standard UPnP AVTransport method for seamless track transitions.
3. High Polling Frequency
- Total AVTransport requests: 156
- Pattern: Continuous polling with
GetPositionInfo and GetTransportInfo every ~800ms
- This suggests Symfonium relies on polling to detect playback state changes
Root Cause Analysis
The Problem
When a track finishes playing on the Xiaomi AI Speaker and Symfonium sends the transition commands, the following occurs:
- Stop command sent (22:15:59.479)
- Xiaomi speaker stops playback
- Speaker state changes to STOPPED
- During this time, the speaker may reset or reload the current URI
- 2.29 second gap (22:15:59.479 to 22:16:01.765)
- This is a critical window where the device behavior is undefined
- The Xiaomi speaker may:
- Return to the beginning of the current track
- Re-load the previous URI
- Enter a default “repeat one” mode
- Wait for new commands
- SetAVTransportURI + Play commands sent (22:15:59.517 and 22:16:01.765)
- May arrive too late
- May be ignored if device already restarted the previous track
- May fail if device entered an unexpected state during the gap
Why This Happens
The Xiaomi AI Speaker appears to have a default behavior of reloading/replaying the current URI when playback stops without a pre-set next track. This is a common implementation in many DLNA renderers to handle cases where no next track is defined.
UPnP AVTransport Specification Context
According to the UPnP AVTransport service specification, there are two playback control models:
Push Mode (What Symfonium uses)
- Control point (Symfonium) manages the playlist
- Control point must actively send new URIs after each track completes
- Problem: Creates timing gaps and race conditions
- Device behavior during the gap is implementation-dependent
Pull Mode (Recommended)
- Control point uses
SetNextAVTransportURI to preload the next track
- Device automatically transitions to the next track when current one finishes
- Advantage: No timing gaps, seamless transitions
- Device maintains control of the transition timing
Proposed Solutions
Solution 1: Implement SetNextAVTransportURI (Recommended)
How it works:
When starting playback:
1. SetAVTransportURI (Track 1)
2. SetNextAVTransportURI (Track 2) ← Critical addition
3. Play
When Track 1 finishes:
- Device automatically loads Track 2
- Device automatically starts playing Track 2
- No intervention needed from control point
When Track 2 starts:
- SetNextAVTransportURI (Track 3)
- Continue pattern for entire playlist
Benefits:
- Seamless track transitions
- No timing gaps
- Compatible with DLNA specification
- Works reliably across different renderer implementations
Solution 2: Event-Based Transition with Immediate Response
How it works:
- Subscribe to AVTransport events (UPnP eventing)
- Monitor
LastChange events for TransportState = “STOPPED”
- Immediately send
SetAVTransportURI + Play upon receiving the event
- Minimize the gap between stop and next track
Benefits:
- Faster response than polling
- Reduces the gap window
- More efficient than continuous polling
Solution 3: Predictive Pre-loading
How it works:
- Monitor
GetPositionInfo for track position
- When position reaches ~95% of track duration
- Send
SetAVTransportURI for the next track immediately
- Device will be ready to switch when current track ends
Benefits:
- Proactive rather than reactive
- Reduces race conditions
- Works even without SetNextAVTransportURI support
Comparative Analysis
Observed Behavior Patterns
| Aspect |
Symfonium |
Windows Media Player |
| AVTransport Requests |
156 requests (high polling) |
Appears to use eventing |
| Transition Method |
Stop → SetAVTransportURI → Play |
Unknown (incomplete capture) |
| Timing Gap |
~2.29 seconds |
Unknown |
| Next Track Preload |
Not used |
Likely used |
| Event Subscription |
Not observed |
Yes (SUBSCRIBE to AVTransport/event) |
Note: The WMP capture file (wmp.pcapng) did not contain the complete playback session (only SSDP discovery and event subscription), so direct comparison of track transition behavior was not possible. However, WMP’s successful auto-advance behavior suggests it likely uses SetNextAVTransportURI or a more optimized transition method.
Technical Details from Packet Capture
Frame-by-Frame Analysis (symfonium.pcap)
First Track Playback:
Frame 1344: 22:15:24.424 - Stop
Frame 1444: 22:15:24.472 - SetAVTransportURI (River Flows In You)
Frame 2550: 22:15:35.133 - Seek to 00:03:38
Track Transition:
Frame 5605: 22:15:59.479 - Stop (Track 1 finished)
Frame 5652: 22:15:59.517 - SetAVTransportURI (Party Train)
Frame 6518: 22:16:01.765 - Play
Polling Pattern:
- Frames 1189-6635: Continuous GetPositionInfo/GetTransportInfo polling
- Average interval: ~800ms between polls
- Total polling requests: 156
Xiaomi Speaker Response
From frame 1365, we can see the speaker sends a NOTIFY event indicating:
<TransportState val="STOPPED"/>
<CurrentTransportActions val="Next,Previous,Seek,Play"/>
This confirms the speaker supports the Next action, suggesting it expects tracks to be pre-loaded.
Recommendations for Symfonium Development
Short-term Fix
Implement SetNextAVTransportURI when starting playback of each track:
// Pseudocode
void playTrack(Track current, Track next) {
avTransport.SetAVTransportURI(0, current.uri, current.metadata);
if (next != null) {
avTransport.SetNextAVTransportURI(0, next.uri, next.metadata);
}
avTransport.Play(0, "1");
}
Medium-term Enhancement
- Subscribe to AVTransport events instead of polling
- Implement proper event handling for playback state changes
- Use
SetNextAVTransportURI proactively when track position > 90%
Long-term Architecture
- Abstract DLNA control patterns into a state machine
- Support multiple transition strategies (adaptive to renderer capabilities)
- Query renderer capabilities via
GetDeviceCapabilities to choose optimal method
Testing Recommendations
To validate the fix:
- Capture new packet traces with the fix applied
- Verify SetNextAVTransportURI appears in the capture
- Measure transition timing - should be seamless (< 100ms gap)
- Test with multiple renderers to ensure compatibility
- Verify playlist advancement works reliably for 5+ consecutive tracks
Conclusion
The single-track loop issue in Symfonium is caused by the absence of SetNextAVTransportURI usage during track transitions. The current “Stop → SetAVTransportURI → Play” approach creates a timing gap where the Xiaomi AI Speaker (and potentially other DLNA renderers) defaults to reloading the current track.
Implementing SetNextAVTransportURI will resolve this issue and provide seamless track transitions that are both more reliable and compliant with UPnP/DLNA standards.
Supporting Files
symfonium.pcap - Complete packet capture of Symfonium DLNA session
wmp.pcapng - Partial packet capture of WMP DLNA session (discovery and eventing only)