Media Playback IntegrationΒΆ
This page provides an overview of how the playback routes support different media playback technologies (local playback, Chromecast, Android Auto, AirPlay) and how they coordinate with each other.
π― OverviewΒΆ
Mixtape Society supports multiple playback methods to enable flexible listening experiences across different devices and contexts. The playback routes serve as the common backend for all these technologies.
π Playback TechnologiesΒΆ
Technology ComparisonΒΆ
| Technology | Type | Use Case | Server Requirements | Complexity |
|---|---|---|---|---|
| Local Playback | Standard HTML5 | Desktop, mobile browsers | Audio streaming | Low |
| Chromecast | Network casting | TVs, speakers | CORS + Range requests | High |
| Android Auto | Enhanced local | In-car dashboard | Cover optimization | Medium |
| AirPlay | Native iOS | Apple devices | Standard streaming | Low |
When Each is UsedΒΆ
graph TD
User[User Starts Playback]
CheckMode{Check Playback Mode}
Casting{Casting Active?}
AndroidAuto{Android Auto?}
User --> CheckMode
CheckMode --> Casting
Casting -->|Yes| Chromecast[Use Chromecast SDK]
Casting -->|No| AndroidAuto
AndroidAuto -->|Yes| AASession[Enhanced Media Session]
AndroidAuto -->|No| Standard[Standard Media Session]
Chromecast --> CastDevice[Chromecast Device]
AASession --> CarDashboard[Car Dashboard]
Standard --> Browser[Browser Controls]
style Chromecast fill:#4a6fa5,color:#fff
style AASession fill:#c65d5d,color:#fff
style Standard fill:#4a8c5f,color:#fff
π Local PlaybackΒΆ
OverviewΒΆ
Standard HTML5 audio playback in the browser.
How it works:
- Browser requests audio file:
GET /play/path?quality=medium - Server validates and serves file (200 or 206)
- HTML5
<audio>element plays file - Media Session API provides lock screen controls
Server requirements:
- β Audio streaming (Audio Streaming)
- β Quality parameter (Quality & Caching)
- β Range requests optional (Range Requests)
Frontend:
playerControls.js- Playback orchestrationplayerUtils.js- Media Session setup
AdvantagesΒΆ
- β No setup required
- β Works on all modern browsers
- β Simple implementation
- β No network complexity
LimitationsΒΆ
- β Single device only
- β Basic UI controls
- β Limited metadata display
π‘ ChromecastΒΆ
OverviewΒΆ
Network-based casting to TVs and speakers. Browser acts as remote control while audio streams directly from server to Chromecast device.
Architecture:
graph LR
Browser[Browser]
CastSDK[Cast SDK]
Server[Flask Server]
Chromecast[Chromecast Device]
Browser -->|Control commands| CastSDK
CastSDK -->|Media queue| Chromecast
Chromecast -->|Audio requests| Server
Server -->|Audio stream| Chromecast
style CastSDK fill:#4a6fa5,color:#fff
style Chromecast fill:#c65d5d,color:#fff
How it works:
- User clicks cast button
- Browser sends queue to Chromecast via Cast SDK
- Chromecast requests each track from server
- Server streams audio with CORS headers
- Browser controls playback via Cast SDK
Server requirements:
- β
CORS headers:
Access-Control-Allow-Origin: * - β Range request support (required for seeking)
- β Quality parameter support
- β Proper MIME types
Critical headers:
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Expose-Headers"] = \
"Content-Type, Accept-Encoding, Range"
response.headers["Accept-Ranges"] = "bytes"
AdvantagesΒΆ
- β Cast to multiple devices
- β High-quality audio
- β Works across home network
- β Unified controls (lock screen, browser, TV remote)
LimitationsΒΆ
- β Requires Cast-enabled device
- β Same WiFi network required
- β More complex setup
- β iOS has limited support
π Android AutoΒΆ
OverviewΒΆ
Enhanced local playback with in-car dashboard integration. Audio plays on phone while controls and metadata display on car dashboard.
Architecture:
graph LR
Phone[Phone Browser]
MediaSession[Media Session API]
Car[Car Dashboard]
Audio[Audio Element]
Phone -->|Enhanced metadata| MediaSession
MediaSession -->|Display & controls| Car
Audio -->|Plays on phone| Audio
Car -->|User actions| MediaSession
MediaSession -->|Events| Phone
style MediaSession fill:#4a6fa5,color:#fff
style Car fill:#c65d5d,color:#fff
How it works:
- Android Auto detected when phone connects to car
- Enhanced Media Session setup with position state
- Requests multiple cover art sizes (96x96 to 512x512)
- Dashboard displays track info and controls
- Steering wheel buttons/voice commands control playback
Server requirements:
- β Cover art size optimization (5 sizes: 96, 128, 192, 256, 512)
- β Standard audio streaming
- β No CORS headers needed (local playback)
- β No range requests needed (standard seeking)
Key difference from Chromecast:
| Aspect | Chromecast | Android Auto |
|---|---|---|
| Network | WiFi casting | Local playback |
| Server Load | Direct stream to device | Stream to phone |
| CORS | Required | Not required |
| Range Requests | Required | Optional |
| Artwork | 1 size | 5 sizes |
| Complexity | High (SDK + server) | Medium (Media Session only) |
AdvantagesΒΆ
- β Automatic connection (no user action)
- β Safe driving interface
- β Voice command support
- β Steering wheel controls
- β Dashboard display
LimitationsΒΆ
- β Android Auto car/device required
- β Only works in car
- β Single user (driver)
π AirPlayΒΆ
OverviewΒΆ
Native iOS casting to AirPlay-enabled devices.
How it works:
- Safari detects AirPlay-enabled devices
- User taps AirPlay icon in audio controls
- iOS handles streaming to AirPlay device
- Standard playback routes serve audio
Server requirements:
- β Standard audio streaming
- β Quality parameter
- β No special CORS requirements (handled by iOS)
- β No range request requirements
AdvantagesΒΆ
- β Native iOS integration
- β Works with HomePod, Apple TV, AirPlay speakers
- β Multi-room audio (AirPlay 2)
- β Simple implementation (iOS handles everything)
LimitationsΒΆ
- β iOS/macOS only
- β AirPlay-enabled device required
- β Same network required
π Mode CoordinationΒΆ
Player Controls RoutingΒΆ
The playerControls.js module coordinates between playback modes:
function playTrack(index) {
// 1. Check if currently casting
if (globalCastingState) {
console.log('π Routing to Chromecast');
castJumpToTrack(index);
return;
}
console.log('π Playing locally');
// 2. Local playback
const track = trackItems[index];
player.src = `/play/${track.dataset.path}?quality=medium`;
player.play();
// 3. Setup Media Session based on platform
const metadata = extractMetadataFromDOM(track);
if (isAndroidAutoConnected()) {
// Enhanced Media Session for Android Auto
setupAndroidAutoMediaSession(metadata, playerControls, player);
} else {
// Standard Media Session (iOS, Desktop)
setupLocalMediaSession(metadata, playerControls);
}
}
Priority order:
- Chromecast (highest priority)
- If casting is active, all commands route to Cast SDK
-
Local player is silenced
-
Android Auto (medium priority)
- If detected and not casting
-
Enhanced Media Session with position state
-
Standard Playback (fallback)
- Default for iOS, Desktop
- Basic Media Session
Mode SwitchingΒΆ
Chromecast Start:
function onCastSessionStart() {
silenceLocalPlayer(); // Pause and mute local <audio>
clearMediaSession(); // Remove local handlers
updateMediaSessionForCast(); // Set Cast handlers
globalCastingState = true;
}
Chromecast Stop:
function onCastSessionEnd() {
enableLocalPlayer(); // Restore local <audio>
globalCastingState = false;
// Restore appropriate Media Session
if (isAndroidAutoConnected()) {
setupAndroidAutoMediaSession(...);
} else {
setupLocalMediaSession(...);
}
}
ποΈ Quality Parameter UsageΒΆ
All playback modes respect the quality parameter:
By ModeΒΆ
| Mode | Quality Usage | Reason |
|---|---|---|
| Chromecast | Always uses quality param | Network bandwidth optimization |
| Android Auto | Uses quality param | Car data connection limits |
| Desktop | Uses quality param | User preference |
| Mobile (WiFi) | Uses quality param | Battery and bandwidth |
| Mobile (Cellular) | Defaults to low |
Data usage minimization |
URL ConstructionΒΆ
Frontend (playerControls.js):
const currentQuality = localStorage.getItem('audioQuality') || 'medium';
const url = `/play/${track.path}?quality=${currentQuality}`;
Chromecast (chromecast.js):
const mediaInfo = new chrome.cast.media.MediaInfo(
`${baseUrl}/play/${track.file_path}?quality=medium`,
'audio/mpeg'
);
See: Quality & Caching
π οΈ Server Requirements SummaryΒΆ
Required for All ModesΒΆ
@play.route("/play/<path:file_path>")
def stream_audio(file_path):
# β
Path validation
full_path = _resolve_and_validate_path(file_path)
# β
MIME type detection
mime_type = _guess_mime_type(full_path)
# β
Quality-aware caching
quality = request.args.get("quality", "medium")
serve_path = _get_serving_path(full_path, quality)
# β
Serve file
return send_file(serve_path, mimetype=mime_type)
Additional for ChromecastΒΆ
# β
CORS headers
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Expose-Headers"] = \
"Content-Type, Accept-Encoding, Range"
# β
Range request handling
if request.headers.get("Range"):
return _handle_range_request(serve_path, mime_type)
Additional for Android AutoΒΆ
# β
Cover art optimization (separate route)
@play.route("/covers/<slug>_<size>.jpg")
def serve_sized_cover(slug, size):
# Returns optimized cover at requested size
# Sizes: 96x96, 128x128, 192x192, 256x256, 512x512
pass
π Use Case RecommendationsΒΆ
Scenario-Based RecommendationsΒΆ
| Scenario | Recommended Method | Why |
|---|---|---|
| Living room TV | Chromecast | Large screen, shared listening |
| Car dashboard | Android Auto | Automatic, safe driving UI |
| Personal listening | Standard | Simple, no setup |
| Multi-room audio | Chromecast | Cast to multiple devices |
| Offline/low bandwidth | Standard (cached) | No network needed |
| Party/gathering | Chromecast | Share control via QR code |
| Work/background | Standard | Desktop browser |
| iOS user with HomePod | AirPlay | Native iOS integration |
π Detailed DocumentationΒΆ
For complete implementation details, see:
Casting TechnologiesΒΆ
- Chromecast Integration - Complete Cast SDK guide
- SDK setup and initialization
- Queue management
- Media Session synchronization
- CORS and range request requirements
- Platform-specific guidance
-
Troubleshooting
-
Android Auto Overview - Enhanced Media Session guide
- Architecture and detection
- Enhanced Media Session setup
- Artwork optimization (5 sizes)
- Position state management
- Testing procedures
Frontend IntegrationΒΆ
- Player Controls - Playback orchestration
- Mode coordination logic
- Casting state management
- Quality selector
-
Event handling
-
Player Utilities - Shared utilities
- Device detection
- Media Session management
- Player state control
- Metadata extraction
Backend ServicesΒΆ
- Audio Streaming - Core streaming implementation
- Range Requests - Partial content support
- Quality & Caching - Quality management
- Cover Art System - Image optimization
π For DevelopersΒΆ
Adding a New Playback ModeΒΆ
Steps:
- Detect the new mode
// In playerUtils.js
export function detectNewMode() {
// Detection logic
return { isNewMode: true, ... };
}
- Add mode check in playerControls
if (globalCastingState) {
// Chromecast
} else if (isAndroidAutoConnected()) {
// Android Auto
} else if (isNewMode()) {
// New mode
} else {
// Standard
}
- Implement mode-specific setup
// In newMode.js
export function setupNewMode(metadata, controls) {
// Mode-specific initialization
}
- Update server if needed
Debugging Playback IssuesΒΆ
Check in this order:
- Mode detection
console.log('Casting:', globalCastingState);
console.log('Android Auto:', isAndroidAutoConnected());
- Network requests
- Open DevTools β Network tab
- Look for 200/206 responses
-
Check CORS headers
-
Server logs
- Media Session
This overview connects all playback technologies. For implementation details, see the linked documentation.
