# Headless HLS Streaming Implementation

## Overview

The headless HLS streaming functionality has been enhanced to work identically to the Qt player, with proper video completion tracking, message sending, and OVER/UNDER video sequence handling.

## Version Update

**Version: 1.0.14** (updated from 1.0.13)

## Key Features Implemented

### 1. Video Duration Detection
- Uses `ffprobe` to detect video duration in seconds
- Stores duration in `current_video_duration` variable
- Records video start time in `video_start_time` variable

### 2. Timer-Based Video Completion
- Sets up a timer when non-looping videos start
- Timer duration = video duration + 2 seconds (buffer)
- Timer triggers `_on_video_end_timer_expired()` callback
- Ensures videos play completely before moving to next

### 3. Video Completion Handling
The `_handle_video_completion()` method sends appropriate messages based on video type:

- **Match video completion**: Sends `PLAY_VIDEO_MATCH_DONE` message
- **Result video completion**: Sends `PLAY_VIDEO_RESULT_DONE` message
- **Intro video completion**: Switches to black screen

### 4. OVER/UNDER Video Sequence Handling
When a video filename starts with "OVER_" or "UNDER_":

1. Detects OVER/UNDER sequence requirement
2. Creates sequence list with both videos
3. Plays videos in order (OVER then UNDER, or UNDER then OVER)
4. After sequence completes, plays result video
5. Sends `PLAY_VIDEO_MATCH_DONE` for the last OVER/UNDER video

### 5. Message Bus Communication
The headless streamer communicates with other components using the same messages as Qt player:

- **PLAY_VIDEO_MATCH**: Start playing match video
- **PLAY_VIDEO_MATCH_DONE**: Notify match video completed
- **PLAY_VIDEO_RESULT**: Start playing result video
- **PLAY_VIDEO_RESULT_DONE**: Notify result video completed
- **START_INTRO**: Start intro video (loops until next match)

## Workflow

### Normal Match Flow
```
1. START_INTRO received
   → Play INTRO video (looping)
   
2. PLAY_VIDEO_MATCH received
   → Stop intro
   → Play match video (non-looping)
   → Set completion timer
   
3. Timer expires / video ends
   → Send PLAY_VIDEO_MATCH_DONE
   → Switch to black screen
   
4. PLAY_VIDEO_RESULT received
   → Play result video (non-looping)
   → Set completion timer
   
5. Timer expires / video ends
   → Send PLAY_VIDEO_RESULT_DONE
   → Switch to black screen
   
6. START_INTRO received (for next match)
   → Back to step 1
```

### OVER/UNDER Match Flow
```
1. START_INTRO received
   → Play INTRO video (looping)
   
2. PLAY_VIDEO_MATCH received (OVER_xxx.mp4 or UNDER_xxx.mp4)
   → Detect OVER/UNDER sequence
   → Play OVER video (non-looping)
   → Set completion timer
   
3. Timer expires / OVER video ends
   → Send PLAY_VIDEO_MATCH_DONE for OVER
   → Play UNDER video (non-looping)
   → Set completion timer
   
4. Timer expires / UNDER video ends
   → Send PLAY_VIDEO_MATCH_DONE for UNDER
   → Play result video (non-looping)
   → Set completion timer
   
5. Timer expires / result video ends
   → Send PLAY_VIDEO_RESULT_DONE
   → Switch to black screen
   
6. START_INTRO received (for next match)
   → Back to step 1
```

## Usage

### Starting Headless Mode

```bash
# Start application in headless mode
python main.py --headless

# With custom streamer port
python main.py --headless --streamer-port 5884

# With test mode (auto-starts intro)
python main.py --headless --test-stream
```

### Viewing the Stream

1. Open VLC Media Player
2. File → Open Network Stream
3. Enter: `http://127.0.0.1:5884/mbetterc_stream.m3u8`
4. Click Play

### Testing

Run the test script to verify functionality:

```bash
python test_headless_streaming.py
```

This will:
- Start the headless streamer
- Simulate games_thread behavior
- Send test messages (INTRO → MATCH → RESULT → INTRO)
- Verify message sending and video completion
- Log all events for debugging

## Technical Details

### Video Duration Detection

```python
def _get_video_duration(self, video_path: str) -> float:
    """Get video duration in seconds using ffprobe"""
    cmd = [
        'ffprobe',
        '-v', 'error',
        '-show_entries', 'format=duration',
        '-of', 'default=noprint_wrappers=1:nokey=1',
        str(video_path)
    ]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
    if result.returncode == 0:
        return float(result.stdout.strip())
    return 0.0
```

### Timer Setup

```python
# Set up video completion timer if not looping
if not loop and duration > 0:
    timer_delay = duration + 2.0  # Add buffer
    logger.info(f"Setting video completion timer for {timer_delay:.2f} seconds")
    self.video_end_timer = threading.Timer(timer_delay, self._on_video_end_timer_expired)
    self.video_end_timer.daemon = True
    self.video_end_timer.start()
```

### Message Sending

```python
# Match video completed
if self.current_video_type == 'match':
    done_message = MessageBuilder.play_video_match_done(
        sender=self.name,
        match_id=self.current_match_id,
        video_filename=self.current_match_video_filename,
        fixture_id=self.current_fixture_id
    )
    self.message_bus.publish(done_message, broadcast=True)

# Result video completed
elif self.current_video_type == 'result':
    done_message = MessageBuilder.play_video_result_done(
        sender=self.name,
        fixture_id=self.current_fixture_id,
        match_id=self.current_match_id,
        result=self.current_result
    )
    self.message_bus.publish(done_message, broadcast=True)
```

## Files Modified

1. **mbetterclient/core/rtsp_streamer.py**
   - Added video duration detection
   - Added timer-based completion tracking
   - Added OVER/UNDER sequence handling
   - Added proper message sending on video completion
   - Enhanced video switching with loop parameter

2. **build.py**
   - Updated version to 1.0.14

3. **main.py**
   - Updated version to 1.0.14

4. **mbetterclient/config/settings.py**
   - Updated version to 1.0.14
   - Updated user_agent to "MbetterClient/1.0r14"

5. **mbetterclient/__init__.py**
   - Updated version to 1.0.14

6. **mbetterclient/web_dashboard/app.py**
   - Updated version to 1.0.14

7. **test_reports_sync_fix.py**
   - Updated user_agent to "MbetterClient/1.0r14"

8. **test_headless_streaming.py** (new file)
   - Comprehensive test script for headless streaming
   - Simulates games_thread behavior
   - Tests complete workflow

## Integration with Games Thread

The headless streamer integrates seamlessly with the games_thread:

1. **Games thread sends messages**:
   - `START_INTRO`: Start intro video
   - `PLAY_VIDEO_MATCH`: Start match video
   - `PLAY_VIDEO_RESULT`: Start result video

2. **Headless streamer responds**:
   - `PLAY_VIDEO_MATCH_DONE`: Match video completed
   - `PLAY_VIDEO_RESULT_DONE`: Result video completed

3. **Games thread continues**:
   - After `PLAY_VIDEO_MATCH_DONE`: Sends `PLAY_VIDEO_RESULT`
   - After `PLAY_VIDEO_RESULT_DONE`: Sends `NEXT_MATCH` or `START_INTRO`

This ensures the headless streamer works identically to the Qt player from the games_thread's perspective.

## Troubleshooting

### Video Not Playing
- Check FFmpeg is installed: `ffmpeg -version`
- Check ffprobe is available: `ffprobe -version`
- Check video file exists and is readable
- Check logs for errors

### Messages Not Being Sent
- Enable debug mode: `--debug-player`
- Check message bus logs: `--dev-message`
- Verify message handlers are registered

### Timer Not Firing
- Check video duration is detected correctly
- Check timer is started (look for "Setting video completion timer" in logs)
- Check for exceptions in timer callback

### OVER/UNDER Not Working
- Check video filenames start with "OVER_" or "UNDER_"
- Check both videos exist in extracted directory
- Check logs for sequence detection

## Future Enhancements

Potential improvements for future versions:

1. **Real-time progress tracking**: Send VIDEO_PROGRESS messages during playback
2. **Seek support**: Allow seeking within videos (requires FFmpeg restart)
3. **Volume control**: Adjust audio volume dynamically
4. **Multiple audio tracks**: Support for different audio languages
5. **Subtitle support**: Overlay subtitles on video stream

## Conclusion

The headless HLS streaming implementation now provides full parity with the Qt player functionality, including:

✓ Video duration detection
✓ Timer-based completion tracking
✓ Proper message sending (PLAY_VIDEO_MATCH_DONE, PLAY_VIDEO_RESULT_DONE)
✓ OVER/UNDER video sequence handling
✓ Seamless integration with games_thread
✓ Complete workflow support (INTRO → MATCH → RESULT → INTRO)

This allows the application to run in headless mode with full video playback capabilities, suitable for deployment on servers or environments without a display.