Class: VideoProcessing::VideoTranslationService
- Inherits:
-
Object
- Object
- VideoProcessing::VideoTranslationService
- Defined in:
- app/services/video_processing/video_translation_service.rb
Overview
Service to translate video captions and transcripts using AssemblyAI Speech Understanding API
Supports translation to Quebec French (fr-CA), Mexican Spanish (es-MX), and Polish (pl)
Uses native AssemblyAI translation for better quality and efficiency:
- Single API call translates to all languages at once
- Native utterance matching preserves timing
- Falls back to LLM Gateway for individual caption translation if needed
Constant Summary collapse
- SUPPORTED_LOCALES =
Supported target locales with AssemblyAI language codes
{ 'fr-CA' => { language: 'French', variant: 'Quebec French / Canadian French', name: 'Français', assemblyai_code: 'fr' }, 'es-MX' => { language: 'Spanish', variant: 'Mexican Spanish', name: 'Español', assemblyai_code: 'es' }, 'pl' => { language: 'Polish', variant: 'Standard Polish', name: 'Polski', assemblyai_code: 'pl' } }.freeze
Instance Attribute Summary collapse
-
#video ⇒ Object
readonly
Returns the value of attribute video.
Class Method Summary collapse
-
.available_translations(video) ⇒ Object
Get available translations for a video.
Instance Method Summary collapse
-
#initialize(video) ⇒ VideoTranslationService
constructor
A new instance of VideoTranslationService.
-
#translate_captions(locales = SUPPORTED_LOCALES.keys, &progress_callback) {|83, "Translating to #{valid_locales.length} languages..."| ... } ⇒ Hash
Translate VTT captions to specified locales using AssemblyAI LLM Gateway Translates the POLISHED captions, preserving our terminology and grammatical fixes.
-
#translate_transcript(locales = SUPPORTED_LOCALES.keys) ⇒ Hash
Translate plain transcript text to specified locales.
Constructor Details
#initialize(video) ⇒ VideoTranslationService
Returns a new instance of VideoTranslationService.
21 22 23 |
# File 'app/services/video_processing/video_translation_service.rb', line 21 def initialize(video) @video = video end |
Instance Attribute Details
#video ⇒ Object (readonly)
Returns the value of attribute video.
19 20 21 |
# File 'app/services/video_processing/video_translation_service.rb', line 19 def video @video end |
Class Method Details
.available_translations(video) ⇒ Object
Get available translations for a video
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'app/services/video_processing/video_translation_service.rb', line 76 def self.available_translations(video) return [] unless video.structured_transcript_json.present? translations = [] SUPPORTED_LOCALES.each_key do |locale| vtt_key = "vtt_#{locale.underscore}" next unless video.structured_transcript_json[vtt_key].present? translations << { locale: locale, name: SUPPORTED_LOCALES[locale][:name], caption_count: video.structured_transcript_json[vtt_key].length } end translations end |
Instance Method Details
#translate_captions(locales = SUPPORTED_LOCALES.keys, &progress_callback) {|83, "Translating to #{valid_locales.length} languages..."| ... } ⇒ Hash
Translate VTT captions to specified locales using AssemblyAI LLM Gateway
Translates the POLISHED captions, preserving our terminology and grammatical fixes
30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'app/services/video_processing/video_translation_service.rb', line 30 def translate_captions(locales = SUPPORTED_LOCALES.keys, &progress_callback) Rails.logger.debug("Translating captions", video_id: @video.id, locale_count: locales&.size) return { success: false, error: 'No polished VTT available' } unless @video.has_polished_vtt? # Filter to valid locales valid_locales = locales.map(&:to_s).select { |l| SUPPORTED_LOCALES.key?(l) } yield(83, "Translating to #{valid_locales.length} languages...") if progress_callback # Translate polished captions using LLM Gateway translate_polished_captions(valid_locales, &progress_callback) end |
#translate_transcript(locales = SUPPORTED_LOCALES.keys) ⇒ Hash
Translate plain transcript text to specified locales
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'app/services/video_processing/video_translation_service.rb', line 47 def translate_transcript(locales = SUPPORTED_LOCALES.keys) Rails.logger.debug("Translating transcript", video_id: @video.id, locale_count: locales&.size) return { success: false, error: 'No transcript available' } if @video.transcript.blank? results = {} locales.each do |locale| locale_str = locale.to_s next unless SUPPORTED_LOCALES.key?(locale_str) begin translated_text = translate_text(@video.transcript, locale_str) @video.send(:"transcript_#{locale_str.underscore}=", translated_text) results[locale_str] = { success: true, length: translated_text.length } rescue StandardError => e Rails.logger.error "Failed to translate transcript to #{locale_str}: #{e.}" results[locale_str] = { success: false, error: e. } end sleep(0.5) unless locale == locales.last end # Save the video with translated transcripts @video.save! if results.values.any? { |r| r[:success] } results end |