Commit graph

84 commits

Author SHA1 Message Date
Vadym Samoilenko
a22fe5c1bc fix: surface ElevenLabs config errors and add availability flag
- Extract actual error message from blob response in previewVoice so
  users see the real API error instead of generic "Failed to generate preview"
- VoicePreviewButton now reads err.message from thrown Error objects
- Add available: bool field to ProviderVoicesResponse; returns false
  when ELEVENLABS_API_KEY is not configured so the frontend can react
  proactively instead of hitting a 400 on preview
- VoiceSelector shows a descriptive config warning when available=false

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 14:17:00 +00:00
Vadym Samoilenko
1e177a6d5c feat: add ElevenLabs voice selection to frontend and backend
Add dynamic ElevenLabs voice catalog with provider toggle in the UI,
allowing users to browse ElevenLabs voices, configure stability and
similarity boost settings, and preview/synthesize with ElevenLabs TTS.

Backend:
- New elevenlabs_voices.py service with 1-hour cached API fetching
- TTS routes support ?provider= query param for voices and options
- Preview endpoint routes to ElevenLabs or Gemini based on provider
- stability/similarity_boost params flow through TTS synthesis pipeline
- TTSPreferences model extended with ElevenLabs-specific fields
- Deprecated hardcoded elevenlabs_voices config (now fetched dynamically)

Frontend:
- Provider toggle (Gemini/ElevenLabs) in VoiceSelector
- ElevenLabsSettingsPanel with stability and similarity boost sliders
- VoicePreviewButton supports provider-specific preview parameters
- API client passes provider param to voices, options, and preview endpoints
- New VoiceInfo, ProviderVoicesResponse, ProviderOptionsResponse types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:58:56 +00:00
michael
0c3102b77f feat: add Return to QC action for jobs in resting statuses
Allow production/admin users to move jobs back to pending_qc from
completed, pending_final_review, rejected, qc_feedback, tts_failed,
render_failed, approved_english, and approved_source statuses. Includes
single-job endpoint, bulk endpoint, JobDetail inline form with required
notes, bulk action in JobsList with confirmation modal, and a Review
Notes card on the job overview tab.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 13:18:02 -06:00
michael
89a902d392 fix: prevent pause point input reset during editing
Changed useEffect dependency from full pausePoint object to just
cue_index. This prevents the input from resetting when parent re-renders
cause the pausePoint object reference to change while editing the same
pause point.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 10:09:07 -06:00
michael
106ca49f6f fix: allow free-form editing of pause point timestamp input
The input was reformatting with .toFixed(3) on every keystroke, causing
backspace to appear to insert random digits. Changed to string-based
input state with conversion/validation only on blur or save.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 14:50:44 -06:00
michael
df721850e0 fix: queue TTS regeneration for shifted cues when deleting AD cue
When an AD cue is deleted, all subsequent cues shift positions but their
MP3 files remain at the old indices. This adds handling to automatically
queue TTS regeneration for all cues that shifted after a deletion.

Changes:
- VttEditor: Add onCueDeleted callback to notify parent of deletions
- QCDetail: Track deletion context and queue TTS for all shifted cues

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 14:29:25 -06:00
michael
577ed44dab fix: queue TTS regeneration for shifted cues when inserting AD cue
When a new AD cue is inserted in the middle of existing cues, the system
now automatically queues TTS regeneration for the new cue AND all cues
that shifted positions. This ensures MP3 file indices stay synchronized
with VTT cue indices, preventing cues from being silently dropped during
re-render.

Changes:
- VttEditor: Add onCueInserted callback to notify parent of insertions
- QCDetail: Track insertion context and queue TTS for all shifted cues
- rerender_accessible_video: Add warning log when cue/MP3 count mismatch

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 14:24:36 -06:00
michael
dab294f18a feat: streamline QC approval to skip translation pipeline
QC approval now transitions jobs directly to pending_final_review
since translation, TTS, and accessible video rendering happen before
QC review. Removes unnecessary translate_and_synthesize_task trigger
on approval.

- Update approve_source() to use PENDING_FINAL_REVIEW status
- Update bulk_approve_jobs() to use PENDING_FINAL_REVIEW status
- Remove translate_and_synthesize_task.delay() calls from both endpoints
- Update JobDetail progress indicator to reflect new flow
- Update CLAUDE.md state machine documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 10:37:37 -06:00
michael
48bcea349e feat: add cue numbering to AD cues in VttEditor
Display 0-based cue index badges in the editable AD cue list to match
the numbering shown on the timeline preview, helping users associate
timeline markers with their corresponding editable cues.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 10:28:48 -06:00
michael
0919dbf7bd feat: move accessible video method selection to job creation
Since accessible video is now rendered immediately on upload, the method
selection (pause_insert vs overlay) is moved from QC Review to the New
Job panel. The bulk approval modal for selecting the method is removed.

- Add method selector UI to NewJob.tsx below accessible video checkbox
- Remove method selector from QCDetail.tsx approval flow
- Remove bulk approval modal from QCList.tsx

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 10:25:40 -06:00
michael
e371dc401a feat: add save button to voice settings panel for TTS regeneration
Add ability to save voice settings changes in QC Review screen without
needing to approve the job. When saved, all TTS segments are regenerated
across all languages with the new voice settings.

Changes:
- Add PUT /jobs/{id}/tts-preferences endpoint to update TTS preferences
- Add UpdateTTSPreferencesRequest schema
- Add updateTTSPreferences API method and useUpdateTTSPreferences hook
- Add Save Voice Settings button with change detection to QCDetail

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 09:05:56 -06:00
michael
b9c2fd93ac feat: streamline VTT cue editing to single-step save
Eliminate the two-step save process for VTT cue edits. Previously users
had to (1) save individual cue edits, then (2) click "Save Changes" in
a separate yellow notification box. Now saving a cue immediately persists
to the database and queues TTS regeneration for AD cues.

Changes:
- Add onCueSave callback prop to VttEditor for immediate persistence
- Add per-cue saving indicators and error handling with retry
- Remove hasUnsavedChanges state and yellow "Unsaved Changes" box
- Remove Ctrl+S keyboard shortcut (no longer needed)
- AD cue saves automatically queue TTS regeneration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 08:52:23 -06:00
michael
9d56306052 fix: display pause point timing in seconds instead of milliseconds
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 08:32:34 -06:00
michael
f47820a6a4 fix: make source_ms optional for backward compatibility with existing jobs
Existing jobs in the database don't have source_ms field. Making it
optional allows the API to load these jobs without validation errors.
The re-render task already handles the fallback to original_ms when
source_ms is None.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 07:04:08 -06:00
michael
a6cd4cde07 fix: store source video coordinates in pause points for correct re-rendering
The re-render task was using pause point coordinates from the accessible
video timeline (which includes freeze frame durations) instead of the
original source video coordinates. This caused pause points to exceed
the source video duration and get clamped incorrectly.

Changes:
- Add source_ms field to PausePointData model to store source video cut point
- Update video_renderer.py to populate source_ms when building pause points
- Update rerender_accessible_video.py to use source_ms for placement calculations
- Apply user adjustments as relative offsets (delta-based adjustment)
- Update API responses and TypeScript types to include source_ms
- Add backward compatibility fallback for jobs without source_ms

Note: Existing jobs need to be re-processed from initial render to populate
the new source_ms field.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 10:48:41 -06:00
michael
676490ac65 feat: auto-queue TTS regeneration when AD script cues are edited
When the user edits the audio description VTT and saves, the system now:
1. Compares original vs current AD cue text
2. Identifies which cues were modified
3. Automatically queues TTS regeneration for modified cues
4. Updates the Render Changes panel to show queued regenerations

This enables the "Render Changes" button when AD script edits are saved,
ensuring the accessible video can be re-rendered with updated TTS audio.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 09:59:04 -06:00
michael
aa6777d2c2 feat: add QC accessible video review and editing capabilities
- Reorder workflow: translations now happen BEFORE QC Review step
- Add language tabs to switch between translated languages in QC
- Add video mode tabs (Original Video / Accessible Video)
- Add interactive timeline preview showing video segments and AD cues
- Enable pause point adjustment with millisecond precision
- Add TTS regeneration queue for selective cue re-synthesis
- Add re-render controls with optional Whisper refinement
- Persist video segments and TTS MP3s to GCS for editability
- Add new RENDERING_QC job status for re-render operations
- Create 5 new API endpoints for accessible video editing
- Add rerender_accessible_video.py Celery task

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 08:32:27 -06:00
michael
e44210ea64 feat: auto-rewrite TTS cues that fail synthesis
When TTS synthesis fails after 3 retries, the system now:
- Sends problematic cue text to Gemini for TTS-safe rewriting
- Updates the VTT file in GCS with rewritten text
- Retries TTS synthesis with the new text
- Records successful rewrites in job.tts_rewrites field

UI changes:
- JobDetail shows amber caution box with original/rewritten text
- JobsList shows warning icon next to jobs with rewrites
- Error display clarifies text shown is "after rewrite attempt"

Files changed:
- backend/app/models/job.py: Add tts_rewrites field
- backend/app/prompts/gemini_tts_rewrite.md: New prompt template
- backend/app/services/gemini.py: Add rewrite_tts_cue method
- backend/app/tasks/tts_synthesis.py: Add VTT update utilities
- backend/app/tasks/translate_and_synthesize.py: Rewrite+retry logic
- frontend/src/types/api.ts: Add TTSRewriteItem type
- frontend/src/routes/jobs/JobDetail.tsx: Caution display
- frontend/src/routes/jobs/JobsList.tsx: Warning indicator

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 14:42:50 -06:00
michael
83e4752327 feat: add server-side zip download for bulk job downloads
Replace sequential browser-based bulk download with server-side zip
generation. When users select "Download All Files" from bulk actions,
the system now creates a single organized .zip file containing all
job assets.

Changes:
- Add POST /jobs/bulk/download endpoint that streams zip to client
- Add BulkDownloadRequest schema for the new endpoint
- Create zip_download.py service with streaming zip generation
- Update frontend to call new endpoint and download single zip file
- Organize files in zip by job title and language subdirectories

Zip structure:
accessible_video_YYYYMMDD_HHMMSS.zip
└── {job_title}/
    ├── source.mp4
    └── {lang}/
        ├── captions.vtt
        ├── ad.vtt
        ├── ad.mp3
        ├── accessible_video.mp4
        └── accessible_captions.vtt

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 15:57:57 -06:00
michael
8bd9be6353 fix: TypeScript type narrowing for TTS error display
Use typeof checks for proper type narrowing of unknown error fields

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 21:41:12 -06:00
michael
6915cf46af feat: add TTS retry functionality with detailed error reporting
- Add POST /jobs/{id}/actions/retry_tts endpoint for retrying TTS
- Frontend shows TTS-specific error details (cue index, blocked text)
- Add "Retry TTS Generation" button on failed jobs
- Guides users to edit problematic AD text before retrying

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 21:39:59 -06:00
michael
9436aa4c6b fix: remove useMemo hook after early returns in QCList
The useMemo hook was placed after early returns (isLoading, error),
which violates React's rules of hooks. Hooks must be called
unconditionally on every render.

Replaced with simple inline computation since the operation is cheap.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 19:22:29 -06:00
michael
c512bdc184 feat: use AD VTT pause points instead of Gemini video analysis
Optimize the accessible video workflow by eliminating the dedicated
Gemini video analysis call for pause point estimation. Instead:

- Use AD VTT cue start times as initial pause points for Whisper refinement
- Add user-selectable accessible video method (pause_insert/overlay) at QC approval
- Add bulk approval API endpoint with method selection
- Add method selector UI to QCDetail page
- Add bulk approval modal to QCList for jobs with accessible video

Benefits:
- Eliminates expensive Gemini API call with video upload
- Faster workflow (~5-15 seconds saved per job)
- Cost savings on Gemini video analysis
- User control over accessible video integration method

Backend changes:
- Add accessible_video_method to RequestedOutputs and ApproveSourceRequest
- Add POST /jobs/bulk/approve endpoint
- Replace Gemini call with _build_placements_from_ad_vtt() helper
- Mark analyze_accessible_video_placement() as deprecated

Frontend changes:
- Add method selector radio buttons to QCDetail
- Add bulk approval modal with method selection to QCList
- Update API client and React Query hooks

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 19:05:45 -06:00
michael
3689653135 refactor: remove manual language selection, always auto-detect
Remove the "Original Video Language" control from job upload form.
All videos now use AI auto-detection for source language, simplifying
the UX and eliminating potential for incorrect manual selection.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 18:42:45 -06:00
michael
a8cc0b65a4 chore: update page title to Video Accessibility Platform
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 10:28:00 -06:00
michael
5e22f15e76 fix: TypeScript errors in JobDetail error display
Use explicit null returns and String() casts for unknown types
from job.error Record to satisfy TypeScript strict mode.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 10:22:20 -06:00
michael
c1c0b876fc feat: add RENDER_FAILED status with error propagation to GUI
- Add RENDER_FAILED job status for when video rendering fails
- Fix _check_accessible_video_completion to detect failures and transition
  job status accordingly (was stuck in RENDERING_VIDEO forever)
- Store detailed error info in job.error including failed_languages array
- Call completion check after failures to properly update job status
- Broadcast WebSocket notification on render failures

Frontend:
- Add render_failed to JobStatus type and StatusBadge (red styling)
- Add tts_failed and render_failed to JobsList STATUS_LABELS
- Enhance JobDetail error display with:
  - Warning icon and prominent styling
  - Error type and message
  - Failed languages list with per-language errors
  - Timestamp of when error occurred
- Update ProgressIndicator to handle failed states with red dot

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 10:18:27 -06:00
michael
0c1c115a8f fix: clarify language selector label
Changed "Target Languages" to "Target Languages for Translation"
for clarity in the new job form.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 09:38:29 -06:00
michael
e0850ca307 fix: include source language in jobs list language count
The Languages column now shows total languages (source + translations)
instead of just translation count, matching other parts of the UI.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 09:33:30 -06:00
michael
d2d8e32819 feat: add video-native translation mode for multi-language content
Add a new "Video Native Mode" translation option that re-processes the
video through Gemini for each target language, generating captions and
audio descriptions directly from visual context. This produces more
natural and culturally appropriate content compared to traditional VTT
text translation.

Changes:
- Add translation_mode field to RequestedOutputs (video_native | traditional)
- Create gemini_ingestion_targeted.md prompt for target language generation
- Add extract_accessibility_targeted() method to Gemini service
- Modify translate_and_synthesize task to handle both translation modes
- Add Translation Mode UI selector in NewJob screen (video_native is default)
- Remove transcreation UI (replaced by video_native mode)
- Remove Google Translate service (replaced by Gemini translation)
- Add LanguageSelector component with searchable dropdown

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 13:50:05 -06:00
michael
81079c2d17 fix: handle race conditions and 404 errors in bulk job deletion
- Deduplicate job IDs to prevent processing same job twice
- Convert GCS blob iterator to list upfront to avoid stale generations
- Clear blob.generation before delete to handle concurrent deletions
- Catch NotFound errors gracefully for already-deleted blobs
- Don't re-raise GCS errors - cleanup failures shouldn't block deletion
- Treat already-deleted jobs as successful (idempotent delete)
- Disable action dropdown during bulk operations in UI
- Show spinner with "Please wait" message during deletion

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 15:46:02 -06:00
michael
e8b940aee8 feat: add TTS_FAILED status and robust error handling for TTS synthesis
Add comprehensive error handling for TTS synthesis failures:

Backend:
- Add TTS_FAILED status to JobStatus enum for failed synthesis jobs
- Add TTSSynthesisError exception with cue index and context tracking
- Improve null-safe error handling in Gemini TTS response parsing
- Add _synthesize_cue_with_retry() with exponential backoff (3 attempts)
- Enhanced error logging with text preview and model context

Frontend:
- Add TTS_FAILED status styling (red badge) in StatusBadge component
- Add tts_failed to JobStatus TypeScript type

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 14:26:07 -06:00
michael
eea1c25ab2 feat: enhance VTT editor with timing editing, cue insert/delete
Add comprehensive editing capabilities to the QC Review VTT editor:
- Inline editable timestamp inputs for start/end times
- Insert cue before/after with midpoint timestamp calculation
- Delete cue with confirmation modal
- Real-time per-cue validation warnings for overlaps
- Hover action buttons (insert before, insert after, delete)

Also fixes VTT parser to properly handle empty/invalid timestamps.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 11:46:24 -06:00
michael
0a79a82b04 fix: resolve race condition preventing captions in batch uploads
The video event listener effect had an empty dependency array, causing it
to run only once on mount. For batch uploads where downloads load slower,
the video element wasn't rendered yet when the effect ran, so listeners
were never attached. Adding currentVideoUrl as a dependency ensures the
effect re-runs when the video becomes available.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 10:59:30 -06:00
michael
70a07f3732 debug: add console logging for caption display troubleshooting
Logs VTT content fetching, parsing, and current caption state
to help diagnose subtitle overlay issues in final review mode.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 22:29:56 -06:00
michael
f68bcab667 fix: include accessible video and re-timed captions in bulk download
The "Download All Files" function was missing accessible_video_mp4 and
accessible_captions_vtt files that the backend provides. Updated both
the bulk download in JobsList and the individual Downloads page to
include all available file types.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 11:08:12 -06:00
michael
0eda72fd23 feat: add review action buttons to job detail page
Show contextual buttons when jobs are ready for review:
- QC Review button (blue) when status is pending_qc
- Final Review button (purple) when status is pending_final_review

Buttons appear dynamically via WebSocket updates without refresh.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 07:47:27 -06:00
michael
5376b89d8c feat: add column headers to Final Review Queue
Added header rows to clarify that "Original only" refers to
"Languages Requested" in both Pending and Completed sections.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 07:35:38 -06:00
michael
be660bbcff fix: parse dates as UTC for correct local time display
Backend returns UTC dates without timezone indicator. Added
parseUTCDate helper that appends 'Z' to ensure JavaScript
correctly interprets dates as UTC and converts to local time.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 07:32:25 -06:00
michael
0966ce717c refactor: remove Original Filename column from jobs table
Users can see the filename on the job detail page if needed.
Search still works on filename even though it's not displayed.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 07:29:36 -06:00
michael
46b0f2c092 feat: add filtering, sorting, and table view to All Jobs tab
- Add created_by_name field to JobResponse schema and API
- Batch-fetch user names in list_jobs endpoint for efficiency
- Convert JobsList from card layout to sortable data table
- Add search box (job name, filename, created by user)
- Add user filter dropdown (populated from current jobs)
- Add status filter dropdown (individual statuses from current jobs)
- Add date range filter (All Time, Last 7 Days, Last 30 Days)
- Add sortable columns: Job Name, Created By, Date Created, Status
- Fetch all jobs for full client-side filtering capability
- Add responsive horizontal scroll for mobile

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 07:16:21 -06:00
michael
41677d28e0 fix: prevent video reset when toast notifications appear
Stabilized video URLs in VideoReviewPlayer to prevent the video from
resetting when WebSocket updates trigger React Query refetches. The
fix stores the initial video URL for each tab and reuses it instead
of using the refreshed signed URL, preventing unnecessary remounts.

Changes:
- Added stableVideoUrls state to cache video URLs per tab
- Removed key prop from video element to prevent forced remounts
- Event listeners now attached once on mount, not on URL change

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 06:54:52 -06:00
michael
396e4e74e0 feat: add rendering_video status for accessible video processing
When jobs with accessible video option enabled enter video rendering
phase, the status now transitions to 'rendering_video' so users can
see why processing is taking longer. This provides better visibility
into the video rendering pipeline.

Changes:
- Added RENDERING_VIDEO status to JobStatus enum
- Updated render_accessible_video task to set new status
- Added status display to StatusBadge, jobStatusMessages
- Included new status in JobsList Translation filter group

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 06:49:46 -06:00
michael
ab063c6a28 fix: ensure jobs list fetches fresh data on mount
Added staleTime: 0 and refetchOnMount: 'always' to useJobs hook to
ensure the jobs list always fetches fresh data when navigating to
the All Jobs tab after creating a new job.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 06:39:30 -06:00
michael
eaabf9cef6 fix: show 'Original only' instead of 'N/A' for jobs without translations
Clarifies the UI when a job has no additional translation languages
requested, making it clearer that the job contains only the original
language assets.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 16:59:55 -06:00
michael
394cf478f5 fix: show 'Original' badge for primary language in Final Review
When a video's source language is non-English (e.g., German), the
language asset was incorrectly marked as 'Translated'. Now correctly
shows 'Original' with a green badge for the primary/source language.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 16:46:07 -06:00
michael
fd68d1ef54 feat: add accessible video validation, remove AI confidence check
- Add validation for accessible_video_gcs (file exists, size 0.1MB-5GB)
- Add validation for retimed_captions_vtt_gcs when accessible video exists
- Add AD Videos count to asset validation panel
- Include retimed captions in VTT file count
- Remove AI confidence from validation panel and backend checks

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 16:41:57 -06:00
michael
3cdea9dfec fix: video review caption sync and event listener issues
- Fix video event listeners not re-attaching when video element remounts
  (add activeTab?.videoUrl to useEffect dependency array)
- Add retimed_captions_vtt to VTT API response for accessible videos
- Use retimed captions for accessible video tab in VideoReviewPlayer

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 16:23:48 -06:00
michael
6effe58dc9 feat: add video review with timestamped notes to Final Review
Add a comprehensive video review feature to the Final Review page that allows
reviewers to watch videos with caption overlays and add timestamped notes.

Backend:
- New ReviewNote model for MongoDB with job_id, asset_key, timestamp, content
- CRUD API endpoints at /jobs/{job_id}/review-notes
- Owner-only edit/delete permissions (admins can bypass)
- Database indexes for efficient querying

Frontend:
- VideoReviewPlayer component with video player and caption overlay
- NotesSidebar for viewing/adding notes with auto-highlight when video reaches timestamp
- SyncedCaptionList with auto-scroll and click-to-seek
- AssetTabs for switching between languages and accessible videos
- React Query hooks with 30s polling for collaborative updates

Features:
- Notes persist to database and are shared across all reviewers
- Notes highlight for 5 seconds when video playback reaches their timestamp
- Click note to seek video to that position
- Pause video to add note at current timestamp
- Accessible videos use retimed captions when available

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 15:30:00 -06:00
michael
80d3866d32 feat: add accessible video (MP4 with embedded audio descriptions)
Add new deliverable type that renders video with audio descriptions embedded.
Supports two AI-determined methods:
- Direct Overlay: ducks original audio and overlays AD TTS (for minimal dialogue)
- Pause-Insert: freeze-frame video, insert AD, re-time subtitles (for significant dialogue)

Backend:
- Add Pydantic schemas for Gemini analysis response
- Add Gemini prompt and analyze_accessible_video_placement() method
- Add video_renderer.py service using FFmpeg for both rendering methods
- Add vtt_retimer.py service for pause-insert subtitle adjustment
- Add render_accessible_video.py Celery task
- Modify TTS service to return individual per-cue segments
- Update translate_and_synthesize.py to save segments and trigger rendering
- Update download endpoint to include accessible video outputs

Frontend:
- Add accessible_video_mp4 checkbox to NewJob form
- Update TypeScript types for new deliverable

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 11:06:41 -06:00