Skip to content

feat: on-demand subtitle tracks for direct-play clients#306

Merged
detain merged 2 commits into
masterfrom
feat/subtitle-endpoint
Jun 23, 2026
Merged

feat: on-demand subtitle tracks for direct-play clients#306
detain merged 2 commits into
masterfrom
feat/subtitle-endpoint

Conversation

@detain

@detain detain commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Phase 4 (phlix-console-client) — subtitle overlay, server side

A direct-play client streams the original container, so it has no HLS .vtt sidecar to read. These two endpoints expose an item's embedded text subtitle tracks on demand:

Method Route Returns
GET /api/v1/media/{id}/subtitles {tracks: [{index, language, label, default, codec, filename}]}
GET /api/v1/media/{id}/subtitles/{index} the track as text/vtt

Implementation (reuses the existing Subtitles toolkit)

  • SubtitleControllerlistTracks runs FfmpegRunner::probeSubtitleExtractor::detectTextTracks (bitmap PGS/VobSub excluded — no text); getTrack extracts one track and returns the cleaned WebVTT.
  • FfmpegRunner::extractSubtitleVttffmpeg -map 0:s:{index} -c:s webvtt -f webvtt (transcodes ASS/SRT/mov_text → WebVTT), via a temp file that is always removed; the markup is then stripped with the existing AssWebVttCleaner.
  • Routes + DI getter wired in Application.php next to playback-info.

Verification

  • Live end-to-end against real ffmpeg: a subrip mkv → detectTextTracks (1 track) → extractSubtitleVtt → valid WebVTT.
  • 7 unit tests (mocked ItemRepository/FfmpegRunner, real SubtitleExtractor): list 404 / tracks (bitmap excluded) / empty-when-missing-file; get-track WebVTT + Content-Type, 404 on not-found / extraction-fail / non-numeric index. Full controllers suite 429 green.
  • phpcs PSR-12 clean; phpstan --level=9 clean on the changed files.

The console client consumes these next; the existing HLS-transcode subtitle path is unchanged.

🤖 Generated with Claude Code

A direct-play client streams the original container and so has no HLS .vtt
sidecar to read. Adds two endpoints that expose embedded TEXT subtitle tracks:

  GET /api/v1/media/{id}/subtitles            list text tracks (ffprobe)
  GET /api/v1/media/{id}/subtitles/{index}    that track extracted as WebVTT

The list reuses SubtitleExtractor::detectTextTracks (bitmap PGS/VobSub excluded);
the fetch adds FfmpegRunner::extractSubtitleVtt (ffmpeg -map 0:s:N -c:s webvtt)
then strips ASS markup via AssWebVttCleaner, through a temp file that is always
removed. Verified end-to-end against real ffmpeg (subrip mkv -> WebVTT).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@codacy-production

codacy-production Bot commented Jun 23, 2026

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 10 high · 13 medium · 46 minor

Alerts:
⚠ 69 issues (≤ 0 issues of at least minor severity)

Results:
69 new issues

Category Results
UnusedCode 3 medium
BestPractice 1 medium
Documentation 17 minor
ErrorProne 8 medium
Security 10 high
CodeStyle 28 minor
Complexity 1 medium
Comprehensibility 1 minor

View in Codacy

🟢 Metrics 53 complexity · 0 duplication

Metric Results
Complexity 53
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.59184% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.81%. Comparing base (8e9e109) to head (52194f3).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/Media/Transcoding/FfmpegRunner.php 0.00% 9 Missing ⚠️
src/Server/Http/Controllers/SubtitleController.php 97.50% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master     #306      +/-   ##
============================================
+ Coverage     58.79%   58.81%   +0.02%     
- Complexity    12454    12476      +22     
============================================
  Files           472      473       +1     
  Lines         41001    41050      +49     
============================================
+ Hits          24106    24145      +39     
- Misses        16895    16905      +10     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Review follow-up: subtitle cue text is real dialogue from inside the file, so
the two routes move into the existing auth-gated marker/extras group instead of
being world-readable. Also extracts a configString() helper and wraps the group
call to satisfy the PSR-12 120-char limit (the Component-Tests code-style gate).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@detain detain merged commit dbc80f6 into master Jun 23, 2026
14 of 15 checks passed
@detain detain deleted the feat/subtitle-endpoint branch June 23, 2026 03:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant