soundwave/docs/AUDIO_SEEKING_FIX.md
Iulian 51679d1943 Initial commit - SoundWave v1.0
- Full PWA support with offline capabilities
- Comprehensive search across songs, playlists, and channels
- Offline playlist manager with download tracking
- Pre-built frontend for zero-build deployment
- Docker-based deployment with docker compose
- Material-UI dark theme interface
- YouTube audio download and management
- Multi-user authentication support
2025-12-16 23:43:07 +00:00

7.3 KiB

Audio Seeking Fix - HTTP Range Request Support

Issue

When users attempted to seek through playing audio files (especially YouTube downloads), the progress bar would reset to the start. This issue only affected downloaded files; local files uploaded by users worked correctly.

Root Cause

The backend was using Django's default serve view to deliver media files, which does not support HTTP Range requests. When a browser seeks in an audio/video file, it sends a Range header requesting specific byte ranges. Without proper Range support:

  1. Browser requests bytes at a specific position (e.g., "Range: bytes=1000000-")
  2. Server returns entire file with 200 OK instead of partial content with 206 Partial Content
  3. Browser receives data from the beginning, causing the player to restart

Solution

Implemented a custom media streaming view (serve_media_with_range) with full HTTP Range request support:

Key Features

1. HTTP Range Request Support

  • 206 Partial Content: Returns only requested byte ranges
  • Accept-Ranges header: Advertises range support to browsers
  • Content-Range header: Specifies byte range being returned
  • 416 Range Not Satisfiable: Properly handles invalid range requests

2. Security Enhancements

  • Path Traversal Prevention: Blocks .., absolute paths, and backslashes
  • Symlink Attack Prevention: Verifies resolved paths stay within document root
  • Directory Listing Prevention: Only serves files, not directories
  • Authentication Integration: Works with Django's authentication middleware
  • Security Logging: Logs suspicious access attempts

3. Performance Optimizations

  • Streaming Iterator: Processes files in 8KB chunks to avoid memory issues
  • Cache Headers: Sets appropriate caching (1 hour) for better performance
  • Last-Modified Headers: Enables conditional requests

4. Content Type Detection

Automatically detects and sets proper MIME types for audio formats:

  • .mp3audio/mpeg
  • .m4aaudio/mp4
  • .webmvideo/webm
  • .oggaudio/ogg
  • .wavaudio/wav
  • .flacaudio/flac
  • .aacaudio/aac
  • .opusaudio/opus

Files Modified

Backend Changes

1. /backend/common/streaming.py (NEW)

Custom streaming view with Range request support. This is the core fix that enables seeking.

Key Functions:

  • range_file_iterator(): Efficiently streams file chunks with offset support
  • serve_media_with_range(): Main view handling Range requests and security

2. /backend/config/urls.py

Updated media URL pattern to use the new streaming view:

# Before
re_path(r'^media/(?P<path>.*)$', serve, {...})

# After
re_path(r'^media/(?P<path>.*)$', serve_media_with_range, {...})

Security Analysis

Path Security

Directory Traversal: Blocked by checking for .., /, and \\ Symlink Attacks: Prevented by verifying resolved path stays in document_root Directory Listing: Only files are served, directories return 404

Authentication & Authorization

User Authentication: Handled by Django middleware before view User Isolation: Audio models have owner field with proper filtering Admin Access: Admins can access all files through middleware

Content Security

Content-Type: Proper MIME types prevent content sniffing attacks Inline Disposition: Files play inline rather than forcing download File Validation: Verifies file exists and is readable

Audit Trail

Security Logging: Suspicious access attempts are logged Debug Logging: File not found errors are logged for troubleshooting

Testing Checklist

Functional Testing

  • Seeking works in YouTube downloaded files
  • Seeking works in user-uploaded local files
  • Full file playback works (non-Range requests)
  • PWA mobile playback with seeking
  • Desktop browser playback with seeking

Security Testing

  • Directory traversal attempts blocked (../../../etc/passwd)
  • Absolute path attempts blocked (/etc/passwd)
  • Symlink attacks prevented (resolved path verification)
  • Unauthenticated access blocked (middleware)
  • User isolation maintained (can't access other users' files)

Performance Testing

  • Large file streaming (no memory issues)
  • Multiple simultaneous streams
  • Cache headers work correctly
  • Chunk-based delivery efficient

Browser Compatibility

  • Chrome/Edge (Chromium)
  • Firefox
  • Safari (iOS/macOS)
  • Mobile browsers (PWA)

HTTP Range Request Examples

Full File Request (No Range)

GET /media/audio/example.mp3
→ 200 OK
Content-Length: 5000000
Content-Type: audio/mpeg
Accept-Ranges: bytes

Seek to Middle (Range Request)

GET /media/audio/example.mp3
Range: bytes=2500000-
→ 206 Partial Content
Content-Length: 2500000
Content-Range: bytes 2500000-4999999/5000000
Content-Type: audio/mpeg
Accept-Ranges: bytes

Specific Range Request

GET /media/audio/example.mp3
Range: bytes=1000000-2000000
→ 206 Partial Content
Content-Length: 1000001
Content-Range: bytes 1000000-2000000/5000000
Content-Type: audio/mpeg

Invalid Range Request

GET /media/audio/example.mp3
Range: bytes=9999999-
→ 416 Range Not Satisfiable
Content-Range: bytes */5000000

User Impact

Before Fix

Seeking would restart playback from beginning Poor user experience with downloaded files PWA mobile seeking broken Users had to reload entire file to seek

After Fix

Smooth seeking to any position Instant response to seek operations Works consistently for all file types Better mobile/PWA experience Reduced bandwidth usage (only requested ranges transferred)

Deployment Notes

Container Restart Required

The fix requires restarting the Django application to load the new module:

docker compose restart soundwave

No Database Migrations

No database changes are required - this is a pure code update.

No Configuration Changes

Default settings work for all users. No environment variables or settings updates needed.

Backwards Compatible

  • Existing files continue to work
  • Non-Range requests still supported
  • No breaking changes to API

Future Enhancements

Potential Improvements

  1. Rate Limiting: Add per-user bandwidth throttling
  2. Analytics: Track seeking patterns for insights
  3. CDN Integration: Add support for CDN/proxy caching
  4. Compression: Consider gzip/brotli for text-based formats
  5. Adaptive Streaming: HLS/DASH support for better quality adaptation

Monitoring

Consider adding metrics for:

  • Range request success rate
  • Average seek time
  • Bandwidth usage by file type
  • Failed seek attempts

References

Date

December 16, 2025

Status

IMPLEMENTED AND DEPLOYED


Note: This fix ensures all users (admin and managed users) can seek through audio files without issues. The implementation maintains security, performance, and compatibility while providing a significantly improved user experience.