239 lines
8.2 KiB
Markdown
239 lines
8.2 KiB
Markdown
# Transcoding Fixes Documentation
|
|
|
|
This document describes the fixes implemented to address two critical issues with the video transcoding functionality in NextAV.
|
|
|
|
## Issues Addressed
|
|
|
|
### 1. FFmpeg Process Not Stopped When Video Viewer Closes
|
|
|
|
**Problem**: When users closed the video viewer, FFmpeg transcoding processes continued running in the background, consuming system resources.
|
|
|
|
**Root Cause**:
|
|
- Inadequate cleanup mechanisms in the transcoding API
|
|
- No global process tracking
|
|
- Unreliable client disconnect detection
|
|
|
|
**Solution**:
|
|
- Implemented a **heartbeat mechanism** for reliable player tracking
|
|
- Created a global `ProcessManager` class to track all FFmpeg processes
|
|
- Added automatic cleanup when heartbeat stops for more than 10 seconds
|
|
- Created a DELETE endpoint for manual process termination
|
|
- Added automatic cleanup of stale processes (older than 10 minutes)
|
|
|
|
### 2. Progress Bar Not Showing Correct Progress for Transcoding Streams
|
|
|
|
**Problem**: The video progress bar showed incorrect progress when playing transcoded streams, even though the duration was correctly retrieved. The progress bar would jump and the duration wasn't displaying correctly specifically when transcoding was required.
|
|
|
|
**Root Cause**:
|
|
- Video player components weren't properly reading the `X-Content-Duration` header
|
|
- Duration wasn't being set correctly for transcoded streams
|
|
- Missing duration display in the UI
|
|
- FFmpeg output format wasn't preserving duration metadata properly
|
|
- Progress bar calculation wasn't handling invalid values correctly
|
|
|
|
**Solution**:
|
|
- Enhanced video player components to read duration from response headers
|
|
- Added proper duration handling for both direct and transcoded streams
|
|
- Improved duration display in the UI
|
|
- Added transcoding indicator to show when transcoding is active
|
|
- **Fixed FFmpeg configuration** to preserve duration metadata
|
|
- **Improved progress bar calculation** with better validation
|
|
- **Added duration change event handling** for dynamic updates
|
|
|
|
## Implementation Details
|
|
|
|
### Heartbeat Mechanism (`src/app/api/heartbeat/route.ts`)
|
|
|
|
A reliable system for tracking active video players:
|
|
|
|
```typescript
|
|
// Player sends heartbeat every 5 seconds
|
|
POST /api/heartbeat
|
|
{
|
|
"playerId": "player_1234567890_abc123",
|
|
"videoId": 53
|
|
}
|
|
|
|
// Player notifies disconnect
|
|
DELETE /api/heartbeat
|
|
{
|
|
"playerId": "player_1234567890_abc123"
|
|
}
|
|
|
|
// Check active players
|
|
GET /api/heartbeat
|
|
```
|
|
|
|
**Key Features**:
|
|
- **10-second timeout**: If no heartbeat for 10 seconds, FFmpeg processes are cleaned up
|
|
- **Automatic cleanup**: Background process checks every 5 seconds for stale heartbeats
|
|
- **Player tracking**: Each player has a unique ID for reliable tracking
|
|
- **Video association**: Heartbeats are linked to specific video IDs for targeted cleanup
|
|
|
|
### Process Manager (`src/lib/process-manager.ts`)
|
|
|
|
A global singleton class that manages all FFmpeg processes:
|
|
|
|
```typescript
|
|
class ProcessManager {
|
|
// Register a new FFmpeg process
|
|
register(processId: string, process: any, videoId: string, cleanup: () => void)
|
|
|
|
// Remove a specific process
|
|
remove(processId: string)
|
|
|
|
// Remove all processes for a specific video
|
|
removeByVideoId(videoId: string)
|
|
|
|
// Get all active processes
|
|
getAllProcesses()
|
|
}
|
|
```
|
|
|
|
### Enhanced Transcoding API (`src/app/api/stream/[id]/transcode/route.ts`)
|
|
|
|
Key improvements:
|
|
- Uses `ProcessManager` for process tracking
|
|
- Simplified cleanup (now handled by heartbeat)
|
|
- Proper duration header handling
|
|
- DELETE endpoint for manual cleanup
|
|
|
|
### Updated Video Player Components
|
|
|
|
Both `InlineVideoPlayer` and `VideoViewer` components now:
|
|
- **Send heartbeats**: Every 5 seconds while player is open
|
|
- **Notify disconnect**: When player closes or component unmounts
|
|
- **Track transcoding state**: Show transcoding indicators
|
|
- **Read duration from headers**: Proper progress bar support
|
|
- **Display duration information**: Show video duration in UI
|
|
|
|
## API Endpoints
|
|
|
|
### Heartbeat Management
|
|
- `POST /api/heartbeat` - Send player heartbeat
|
|
- `DELETE /api/heartbeat` - Notify player disconnect
|
|
- `GET /api/heartbeat` - Get status of all active players
|
|
|
|
### Process Management
|
|
- `GET /api/processes` - Get status of all active processes
|
|
- `DELETE /api/processes` - Cleanup all processes
|
|
- `DELETE /api/processes?videoId=123` - Cleanup processes for specific video
|
|
|
|
### Transcoding
|
|
- `GET /api/stream/{id}/transcode` - Start transcoding stream
|
|
- `DELETE /api/stream/{id}/transcode` - Stop transcoding for video
|
|
|
|
## Testing
|
|
|
|
### Test Progress Bar Fixes
|
|
```bash
|
|
node test-progress-bar.mjs
|
|
```
|
|
|
|
### Test Heartbeat Mechanism
|
|
```bash
|
|
node test-heartbeat.mjs
|
|
```
|
|
|
|
### Test Transcoding Fixes
|
|
```bash
|
|
node test-transcoding-fixes.mjs
|
|
```
|
|
|
|
## Monitoring
|
|
|
|
### Check Active Players
|
|
```bash
|
|
curl http://localhost:3000/api/heartbeat
|
|
```
|
|
|
|
### Check Active Processes
|
|
```bash
|
|
curl http://localhost:3000/api/processes
|
|
```
|
|
|
|
### Check Transcoding Headers
|
|
```bash
|
|
curl -I http://localhost:3000/api/stream/54/transcode
|
|
```
|
|
|
|
### Cleanup Specific Video
|
|
```bash
|
|
curl -X DELETE "http://localhost:3000/api/processes?videoId=54"
|
|
```
|
|
|
|
### Cleanup All Processes
|
|
```bash
|
|
curl -X DELETE http://localhost:3000/api/processes
|
|
```
|
|
|
|
## Logs
|
|
|
|
The system now provides detailed logging:
|
|
|
|
```
|
|
[HEARTBEAT] Player player_1234567890_abc123 for video 54 pinged
|
|
[PROCESS_MANAGER] Registered process: transcode_54_1234567890 for video: 54
|
|
[TRANSCODE] Sending response with 1280x720 video stream (progressive duration)
|
|
[PLAYER] Duration from metadata: 581.4s
|
|
[PLAYER] Duration changed: 581.4s
|
|
[HEARTBEAT] Player player_1234567890_abc123 for video 54 timed out, cleaning up FFmpeg processes
|
|
[PROCESS_MANAGER] Removed process: transcode_54_1234567890
|
|
```
|
|
|
|
## How It Works
|
|
|
|
### 1. Player Opens
|
|
1. Video player generates unique `playerId`
|
|
2. Starts sending heartbeats every 5 seconds to `/api/heartbeat`
|
|
3. Backend tracks the player and associates it with the video ID
|
|
|
|
### 2. Transcoding Starts
|
|
1. When transcoding is needed, FFmpeg process is started
|
|
2. Process is registered with `ProcessManager` using the video ID
|
|
3. Player continues sending heartbeats while transcoding
|
|
4. **Duration is discovered progressively** as the stream progresses
|
|
|
|
### 3. Progress Bar Works
|
|
1. **For direct streams**: Duration is fetched from `X-Content-Duration` header
|
|
2. **For transcoded streams**: Duration is discovered progressively via `durationchange` events
|
|
3. **Duration is validated** to prevent NaN values
|
|
4. **Progress calculation** uses validated duration and current time
|
|
5. **Progress clicks** are validated before seeking
|
|
|
|
### 4. Player Closes
|
|
1. Player stops sending heartbeats
|
|
2. After 10 seconds without heartbeat, backend automatically:
|
|
- Removes player from active list
|
|
- Cleans up all FFmpeg processes for that video ID
|
|
3. Alternatively, player can explicitly notify disconnect via DELETE request
|
|
|
|
### 5. Automatic Cleanup
|
|
- Background process runs every 5 seconds
|
|
- Checks for heartbeats older than 10 seconds
|
|
- Automatically cleans up associated FFmpeg processes
|
|
- Prevents resource leaks from crashed or closed players
|
|
|
|
## Benefits
|
|
|
|
1. **Reliable Cleanup**: Heartbeat mechanism ensures FFmpeg processes are always cleaned up
|
|
2. **Resource Efficiency**: No more orphaned processes consuming system resources
|
|
3. **Better UX**: Accurate progress bars and visual feedback
|
|
4. **Monitoring**: Admin tools to track active players and processes
|
|
5. **Transparency**: Users can see when transcoding is active
|
|
6. **Fault Tolerance**: Handles browser crashes, network issues, and unexpected closures
|
|
7. **Progressive Duration**: Progress bar works correctly for transcoded videos without jumping
|
|
8. **Live-like Streaming**: Proper handling of progressive duration discovery
|
|
9. **Smooth Progress**: No more jumping when duration is discovered
|
|
|
|
## Future Improvements
|
|
|
|
1. **Progress Tracking**: Real-time transcoding progress updates via heartbeat
|
|
2. **Quality Selection**: User-selectable transcoding quality
|
|
3. **Caching**: Cache transcoded videos to avoid re-transcoding
|
|
4. **Queue Management**: Handle multiple concurrent transcoding requests
|
|
5. **Error Recovery**: Automatic retry mechanisms for failed transcoding
|
|
6. **Heartbeat Optimization**: Reduce heartbeat frequency for better performance
|
|
7. **Progress Smoothing**: Add interpolation for smoother progress updates
|
|
8. **Duration Caching**: Cache duration values to avoid repeated fetches
|