VideoTools/docs/GSTREAMER_MIGRATION_PLAN.md
Stu Leak 501e2622dc feat(player): integrate GStreamer for stable video playback
- Add GStreamer as mandatory core dependency in install.sh
- Create controller_gstreamer.go wrapping GStreamerPlayer
- Add missing methods to GStreamerPlayer (SetWindow, Stop, SetFullScreen)
- Fix GstSeekFlags type casting issue
- Update build scripts to always use -tags gstreamer
- Update controller_linux.go build tag to exclude when gstreamer enabled
- Add comprehensive migration documentation

GStreamer replaces the broken FFmpeg pipe-based UnifiedPlayer.
GStreamer 1.26+ provides frame-accurate seeking and reliable A/V sync.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 03:43:34 -05:00

364 lines
9.1 KiB
Markdown

# GStreamer Player Migration Plan
**Goal:** Replace the broken FFmpeg pipe-based player with the robust GStreamer implementation.
**Timeline:** 1-2 days (vs. weeks of debugging pipes)
---
## Phase 1: Make GStreamer a Core Dependency ✅ COMPLETE
### What We Did
- Updated `install.sh` to always install GStreamer dev libraries
- Added verification checks for GStreamer presence
- Updated `build-linux.sh` to require GStreamer and fail if missing
- Updated `build.sh` to always use `-tags gstreamer`
### Verification
```bash
# Check GStreamer is installed
pkg-config --modversion gstreamer-1.0
# Should show version like: 1.24.x
```
### Status
**COMPLETE** - Scripts updated, GStreamer is now mandatory
---
## Phase 2: Build and Verify GStreamer Works
### Tasks
1. **Install GStreamer** (if not already done)
```bash
sudo dnf install -y \
gstreamer1-devel \
gstreamer1-plugins-base-devel \
gstreamer1-plugins-good \
gstreamer1-plugins-bad-free \
gstreamer1-plugins-ugly-free \
gstreamer1-libav
```
2. **Build with GStreamer**
```bash
cd /home/stu/Projects/VideoTools
./scripts/build.sh
```
**Expected output:**
```
Checking for GStreamer (required for player)...
GStreamer found (1.24.x)
Building VideoTools with GStreamer player...
Build successful!
```
3. **Test basic playback**
```bash
./VideoTools
# Go to Player module
# Load a test video
# Click Play
```
### Success Criteria
- ✅ Build completes without GStreamer errors
- ✅ VideoTools launches without crashes
- ✅ Player module loads without errors
- ✅ Can load a video file
- ✅ Basic play/pause works
### Troubleshooting
**Build Error: "Package gstreamer-1.0 was not found"**
- Solution: Run `./scripts/install.sh` to install GStreamer
**Runtime Error: "gstreamer playbin unavailable"**
- Solution: Install GStreamer plugins: `sudo dnf install gstreamer1-plugins-base`
---
## Phase 3: Remove UnifiedPlayer Completely
### Tasks
1. **Delete broken FFmpeg pipe player**
```bash
git rm internal/player/unified_ffmpeg_player.go
git rm internal/player/unified_player_adapter.go
```
2. **Update frame_player_default.go**
```go
// Remove build tag (GStreamer is now always used)
package player
func newFramePlayer(config Config) (framePlayer, error) {
return NewGStreamerPlayer(config)
}
```
3. **Remove unused VTPlayer interface (if applicable)**
- Check if `vtplayer.go` interface is still needed
- If not, remove it
4. **Clean up imports**
- Remove any references to UnifiedPlayer
- Run `gofmt` and verify build still works
### Success Criteria
- ✅ UnifiedPlayer files deleted
- ✅ No references to UnifiedPlayer in codebase
- ✅ Build still succeeds
- ✅ Player still works
### Verification
```bash
# Search for any remaining UnifiedPlayer references
grep -r "UnifiedPlayer" internal/player/
# Should return nothing (or only comments)
# Rebuild and test
./scripts/build.sh
./VideoTools
```
---
## Phase 4: Fill Gaps in GStreamer Implementation
Your GStreamer player is already 90% complete, but let's verify and add missing pieces.
### Current Status (from gstreamer_player.go)
| Feature | Status | Line # |
|---------|--------|--------|
| Load video | ✅ Complete | 73-162 |
| Play/Pause | ✅ Complete | 164-186 |
| SeekToTime | ✅ Complete | 188-204 |
| SeekToFrame | ✅ Complete | 206-214 |
| GetFrameImage | ✅ Complete | 229-289 |
| SetVolume | ✅ Complete | 291-301 |
| GetCurrentTime | ✅ Complete | 216-227 |
| Close/cleanup | ✅ Complete | 303-319 |
### Missing Features to Add
#### 4.1: Add GetDuration()
```go
func (p *GStreamerPlayer) GetDuration() time.Duration {
p.mu.Lock()
defer p.mu.Unlock()
if p.pipeline == nil {
return 0
}
var dur C.gint64
if C.gst_element_query_duration(p.pipeline, C.GST_FORMAT_TIME, &dur) == 0 {
return 0
}
return time.Duration(dur)
}
```
#### 4.2: Add GetFrameRate()
```go
func (p *GStreamerPlayer) GetFrameRate() float64 {
p.mu.Lock()
defer p.mu.Unlock()
return p.fps
}
```
#### 4.3: Add Stop() method
```go
func (p *GStreamerPlayer) Stop() error {
p.mu.Lock()
defer p.mu.Unlock()
if p.pipeline != nil {
C.gst_element_set_state(p.pipeline, C.GST_STATE_NULL)
}
return nil
}
```
### Tasks
1. Add missing methods above to `gstreamer_player.go`
2. Ensure `framePlayer` interface in `frame_player.go` matches
3. Update `UnifiedPlayerAdapter` if needed (or remove it - see Phase 3)
4. Test each new method
### Success Criteria
- ✅ All interface methods implemented
- ✅ Duration displays correctly in UI
- ✅ Frame rate is accurate
- ✅ Stop button works properly
---
## Phase 5: Test and Validate All Player Features
### Test Matrix
| Feature | Test Case | Expected Result |
|---------|-----------|----------------|
| **Load** | Drop video file | Video loads, shows duration |
| **Play** | Click play | Smooth playback, no stuttering |
| **Pause** | Click pause | Video freezes, audio stops |
| **Seek** | Drag timeline | Jumps to position accurately |
| **Frame Step** | Use arrow keys | Advances 1 frame at a time |
| **Volume** | Adjust slider | Volume changes smoothly |
| **Mute** | Click mute | Audio cuts off completely |
| **Fullscreen** | Press F | Video fills screen |
| **Multiple Formats** | Load MP4, MKV, AVI | All play correctly |
| **High Resolution** | Load 4K video | Plays without freezing |
| **Long Videos** | Load 2+ hour file | Seeking still accurate |
### Performance Tests
1. **CPU Usage** - Should be <20% during playback (check with `htop`)
2. **Memory Leaks** - Run for 30 minutes, memory should stay stable
3. **Frame Drops** - Monitor for dropped frames during playback
### Integration Tests
1. **Trim Module** - Load video, use frame-accurate seeking
2. **Filters Module** - Apply filter, see real-time preview
3. **Preview System** - Generate thumbnails quickly
### Success Criteria
- All test cases pass
- No crashes during extended playback
- Frame-accurate seeking works perfectly
- CPU/Memory usage is reasonable
- All video formats supported
---
## Timeline Estimate
| Phase | Time | Blockers |
|-------|------|----------|
| Phase 1 | Done | None |
| Phase 2 | 30 minutes | Installing GStreamer |
| Phase 3 | 15 minutes | None (just deleting code) |
| Phase 4 | 1-2 hours | Testing each method |
| Phase 5 | 2-3 hours | Thorough testing |
| **Total** | **4-6 hours** | **vs. weeks on pipes** |
---
## What Changed vs. Old Approach
### Old Way (UnifiedPlayer with FFmpeg pipes)
```
❌ Manual pipe management
❌ Manual A/V sync (never worked right)
❌ Audio disabled to "fix" issues
❌ Frame reading blocks UI
❌ Seeking requires process restart
❌ Weeks of debugging
```
### New Way (GStreamer)
```
✅ GStreamer handles pipes internally
✅ Built-in A/V synchronization
✅ Audio works out of the box
✅ Non-blocking frame extraction
✅ Native frame-accurate seeking
✅ Hours of implementation
```
---
## Rollback Plan (If Needed)
If GStreamer has issues (unlikely):
1. **Keep old code temporarily**
```bash
git mv internal/player/unified_ffmpeg_player.go internal/player/unified_ffmpeg_player.go.bak
```
2. **Revert build scripts**
```bash
git checkout HEAD -- scripts/build*.sh
```
3. **File issue with details**
- GStreamer version: `pkg-config --modversion gstreamer-1.0`
- Error message
- Test video format
But honestly, your GStreamer code is solid. You won't need this.
---
## Key Decision Points
### Should We Keep UnifiedPlayerAdapter?
**Recommendation: DELETE IT**
- It's a compatibility shim for the old player
- GStreamerPlayer already implements the `framePlayer` interface
- Extra layer adds complexity and bugs
- Clean break is better
### What About VTPlayer Interface?
**Recommendation: SIMPLIFY**
Current:
```
framePlayer interface (8 methods) ✅ Used by GStreamer
VTPlayer interface (30+ methods) ❓ Overly complex
```
Keep `framePlayer`, remove or simplify `VTPlayer`.
---
## Post-Migration Cleanup
Once everything works:
1. **Update PROJECT_STATUS.md**
```markdown
| Player | **Implemented** | GStreamer-based, stable playback |
```
2. **Update README.md**
- Add GStreamer to requirements
- Note improved player stability
3. **Archive old commits**
```bash
git tag archive/ffmpeg-pipe-player HEAD~20
git push origin archive/ffmpeg-pipe-player
```
4. **Unblock dependent modules**
- Start Trim module implementation
- Start Filters module implementation
---
## Emergency Contacts / Resources
- **GStreamer Docs**: https://gstreamer.freedesktop.org/documentation/
- **Go CGO Guide**: https://golang.org/cmd/cgo/
- **Similar Projects**:
- Kdenlive (uses GStreamer with Qt)
- Pitivi (uses GStreamer with Python)
---
## Success Definition
You'll know this migration is complete when:
1. Build always uses GStreamer (no fallback)
2. All player features work correctly
3. No UnifiedPlayer code remains
4. You can implement Trim module without player bugs
5. PROJECT_STATUS.md shows Player as "Implemented"
**Estimated completion: Tomorrow** (vs. weeks fighting pipes)