# M3U Library Feature ## Overview The M3U Library feature allows users to upload, store, manage, and selectively import M3U playlist files separately from the main playlist management system. This provides greater flexibility in managing channel sources. ## Features ### 1. Upload M3U Files - **Location**: Settings page → M3U Library section - **Process**: - Click "Upload M3U" button - Select an M3U or M3U8 file - Provide a custom name for easy identification - File is stored persistently in `/app/data/m3u-files` - **File Limits**: 50MB maximum file size - **Supported Formats**: `.m3u`, `.m3u8` ### 2. View Stored Files - **Display Information**: - Custom file name - File size (formatted: B, KB, MB, GB) - Upload date (localized format) - **Empty State**: Shows message when no files are stored ### 3. Rename Files - **Process**: - Click edit icon (pencil) on any file - Enter new name in dialog - Name is updated in database - **Purpose**: Organize files with meaningful names ### 4. Import to Playlists - **TV Import**: - Click "TV" button on any file - Confirms import type - Channels are parsed and added to TV playlist - `is_radio` flag set to `0` - **Radio Import**: - Click "Radio" button on any file - Confirms import type - Channels are parsed and added to Radio playlist - `is_radio` flag set to `1` - **Import Process**: - Parses M3U file using `iptv-playlist-parser` - Creates new playlist if doesn't exist (named after file) - Extracts channel metadata (name, URL, logo, group, tvg_id, etc.) - Adds channels to database with duplicate prevention - Updates playlist channel count ### 5. Delete Files - **Process**: - Click delete icon (trash) on any file - File is removed from database - Physical file is deleted from storage - **Safety**: Only file owner can delete (verified by user_id) ## Backend API ### Endpoints #### `GET /api/m3u-files` - **Auth**: Required (JWT token) - **Returns**: Array of M3U files for current user - **Fields**: id, user_id, name, original_filename, size, created_at, updated_at #### `POST /api/m3u-files/upload` - **Auth**: Required - **Body**: FormData with `m3u` file and `name` string - **Returns**: Created file object - **Validation**: File type, size, name required #### `PATCH /api/m3u-files/:id` - **Auth**: Required - **Body**: `{ name: string }` - **Returns**: Updated file object - **Validation**: Ownership, name required #### `DELETE /api/m3u-files/:id` - **Auth**: Required - **Returns**: Success message - **Action**: Deletes from DB and filesystem #### `POST /api/m3u-files/:id/import` - **Auth**: Required - **Body**: `{ type: "tv" | "radio" }` - **Returns**: Import summary with playlist_id, channels_added, type - **Process**: Parses M3U, creates/updates playlist, adds channels ## Database Schema ### `m3u_files` Table ```sql CREATE TABLE m3u_files ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, name TEXT NOT NULL, original_filename TEXT NOT NULL, file_path TEXT NOT NULL, size INTEGER NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); CREATE INDEX idx_m3u_files_user ON m3u_files(user_id); ``` ## File Storage ### Location - **Container Path**: `/app/data/m3u-files/` - **Docker Volume**: `streamflow-data:/app/data` - **Permissions**: Owned by `appuser:appgroup` (UID/GID 1001) - **Naming**: `{timestamp}-{random}.m3u` (e.g., `1703001234567-123456789.m3u`) ### Security - Files stored outside web root - User authentication required for all operations - Ownership verification on modify/delete - File type validation on upload - Size limits enforced (50MB) ## Internationalization ### English (en.json) ```json "settings": { "m3uLibrary": "M3U Library", "uploadM3u": "Upload M3U", "noM3uFiles": "No M3U files stored. Upload files to manage them separately.", "uploadM3uFile": "Upload M3U File", "fileName": "File Name", "fileNameHelper": "Give this M3U file a name for easy identification", "selectM3uFile": "Select M3U File", "renameM3uFile": "Rename M3U File", "importM3uFile": "Import M3U File", "importMessage": "Import this M3U file as a {{type}} playlist?", "importInfo": "The channels from this file will be added to your {{section}} section.", "liveTV": "Live TV" }, "common": { "upload": "Upload", "rename": "Rename", "import": "Import", "tv": "TV", "radio": "Radio" } ``` ### Romanian (ro.json) ```json "settings": { "m3uLibrary": "Bibliotecă M3U", "uploadM3u": "Încarcă M3U", "noM3uFiles": "Nu există fișiere M3U stocate. Încarcă fișiere pentru a le gestiona separat.", "uploadM3uFile": "Încarcă Fișier M3U", "fileName": "Nume Fișier", "fileNameHelper": "Dă acestui fișier M3U un nume pentru identificare ușoară", "selectM3uFile": "Selectează Fișier M3U", "renameM3uFile": "Redenumește Fișier M3U", "importM3uFile": "Importă Fișier M3U", "importMessage": "Importă acest fișier M3U ca playlist {{type}}?", "importInfo": "Canalele din acest fișier vor fi adăugate în secțiunea {{section}}.", "liveTV": "TV Live" }, "common": { "upload": "Încarcă", "rename": "Redenumește", "import": "Importă", "tv": "TV", "radio": "Radio" } ``` ## Use Cases ### 1. Testing Multiple M3U Sources Upload several M3U files from different providers, give them descriptive names, then selectively import the best ones. ### 2. Separate TV and Radio Management Upload a large M3U file once, then import TV channels to TV playlist and radio channels to Radio playlist separately. ### 3. Backup and Version Control Keep multiple versions of M3U files with different names (e.g., "Provider A - January 2024", "Provider B - Backup"). ### 4. Offline Preparation Upload M3U files when you have good internet, then import them later when needed without re-downloading. ## Technical Notes ### M3U Parsing - Uses `iptv-playlist-parser` npm package - Extracts metadata: name, url, logo, group, tvg_id, tvg_name, tvg_language, tvg_country - Handles both M3U and M3U8 formats - Preserves channel attributes for EPG matching ### Error Handling - File upload failures cleaned up (temp file deleted) - Parse errors reported to user - Database transactions for import atomicity - Missing physical files handled gracefully on delete ### Performance - Asynchronous file operations - Database indexes on user_id for fast queries - Duplicate channel prevention (INSERT OR IGNORE) - Batch insert for channels during import ## Future Enhancements ### Potential Features - [ ] M3U file preview before import - [ ] Selective channel import (choose which channels to import) - [ ] M3U file validation and health check - [ ] Auto-update from URL for stored M3U files - [ ] Export modified playlists back to M3U format - [ ] Merge multiple M3U files - [ ] Channel deduplication across M3U files - [ ] M3U file sharing between users (admin feature) ## Related Documentation - [SETUP.md](SETUP.md) - Application setup and deployment - [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md) - Codebase organization - [ARCHITECTURE.md](ARCHITECTURE.md) - System architecture overview