Skip to content

Streaming

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
Hold "Alt" / "Option" to enable pan & zoom

πŸ”Š Local PlaybackΒΆ

OverviewΒΆ

Standard HTML5 audio playback in the browser.

How it works:

  1. Browser requests audio file: GET /play/path?quality=medium
  2. Server validates and serves file (200 or 206)
  3. HTML5 <audio> element plays file
  4. Media Session API provides lock screen controls

Server requirements:

Frontend:

  • playerControls.js - Playback orchestration
  • playerUtils.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
Hold "Alt" / "Option" to enable pan & zoom

How it works:

  1. User clicks cast button
  2. Browser sends queue to Chromecast via Cast SDK
  3. Chromecast requests each track from server
  4. Server streams audio with CORS headers
  5. 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"

See: Chromecast Integration

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
Hold "Alt" / "Option" to enable pan & zoom

How it works:

  1. Android Auto detected when phone connects to car
  2. Enhanced Media Session setup with position state
  3. Requests multiple cover art sizes (96x96 to 512x512)
  4. Dashboard displays track info and controls
  5. 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)

See: Android Auto Integration

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:

  1. Safari detects AirPlay-enabled devices
  2. User taps AirPlay icon in audio controls
  3. iOS handles streaming to AirPlay device
  4. 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:

  1. Chromecast (highest priority)
  2. If casting is active, all commands route to Cast SDK
  3. Local player is silenced

  4. Android Auto (medium priority)

  5. If detected and not casting
  6. Enhanced Media Session with position state

  7. Standard Playback (fallback)

  8. Default for iOS, Desktop
  9. 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ΒΆ


πŸŽ“ For DevelopersΒΆ

Adding a New Playback ModeΒΆ

Steps:

  1. Detect the new mode
// In playerUtils.js
export function detectNewMode() {
    // Detection logic
    return { isNewMode: true, ... };
}
  1. Add mode check in playerControls
if (globalCastingState) {
    // Chromecast
} else if (isAndroidAutoConnected()) {
    // Android Auto
} else if (isNewMode()) {
    // New mode
} else {
    // Standard
}
  1. Implement mode-specific setup
// In newMode.js
export function setupNewMode(metadata, controls) {
    // Mode-specific initialization
}
  1. Update server if needed
# Add any required headers or endpoints

Debugging Playback IssuesΒΆ

Check in this order:

  1. Mode detection
console.log('Casting:', globalCastingState);
console.log('Android Auto:', isAndroidAutoConnected());
  1. Network requests
  2. Open DevTools β†’ Network tab
  3. Look for 200/206 responses
  4. Check CORS headers

  5. Server logs

tail -f logs/app.log | grep "Streaming"
  1. Media Session
// Check if active
console.log('Media Session:', navigator.mediaSession.metadata);

This overview connects all playback technologies. For implementation details, see the linked documentation.