- 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
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:
- Browser requests bytes at a specific position (e.g., "Range: bytes=1000000-")
- Server returns entire file with 200 OK instead of partial content with 206 Partial Content
- 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:
.mp3→audio/mpeg.m4a→audio/mp4.webm→video/webm.ogg→audio/ogg.wav→audio/wav.flac→audio/flac.aac→audio/aac.opus→audio/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 supportserve_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
- Rate Limiting: Add per-user bandwidth throttling
- Analytics: Track seeking patterns for insights
- CDN Integration: Add support for CDN/proxy caching
- Compression: Consider gzip/brotli for text-based formats
- 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.