Class: VideoTranscriptionCompletionWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Worker
Defined in:
app/workers/video_transcription_completion_worker.rb

Overview

Worker to process completed AssemblyAI video transcriptions.
Triggered by webhook after AssemblyAI finishes transcribing.

This worker:

  1. Fetches the completed transcript from AssemblyAI
  2. Retrieves VTT captions
  3. Polishes the transcript with company terminology
  4. Generates SEO metadata
  5. Generates content embeddings for semantic search
  6. Sends email notification to the user who submitted the job

Examples:

Queue processing for a completed transcription

VideoTranscriptionCompletionWorker.perform_async(
  video_id: 123,
  transcript_id: 'abc123'
)

Instance Method Summary collapse

Instance Method Details

#perform(options = {}) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/workers/video_transcription_completion_worker.rb', line 25

def perform(options = {})
  @options = options.symbolize_keys
  video_id = @options[:video_id]
  transcript_id = @options[:transcript_id]

  unless video_id && transcript_id
    Rails.logger.error '[VideoTranscriptionCompletionWorker] Missing video_id or transcript_id'
    return
  end

  @video = Video.find_by(id: video_id)
  unless @video
    Rails.logger.error "[VideoTranscriptionCompletionWorker] Video #{video_id} not found"
    return
  end

  Rails.logger.info "[VideoTranscriptionCompletionWorker] Processing Video #{video_id}, transcript: #{transcript_id}"

  begin
    # Update transcript ID if different
    @video.update!(assemblyai_transcript_id: transcript_id) if @video.assemblyai_transcript_id != transcript_id

    # Create transcription service
    service = VideoProcessing::TranscriptionService.new(@video)

    # Step 1: Retrieve VTT from AssemblyAI
    Rails.logger.info '[VideoTranscriptionCompletionWorker] Retrieving VTT captions...'
    service.retrieve_and_overwrite_structured_transcript

    # Step 2: Polish transcript with company terminology
    if @video.vtt_original_data.present?
      Rails.logger.info '[VideoTranscriptionCompletionWorker] Polishing transcript...'
      service.polish_transcript_with_company_terminology
    end

    # Step 3: Generate SEO metadata
    if @video.structured_transcript_paragraphs.present?
      Rails.logger.info '[VideoTranscriptionCompletionWorker] Generating SEO metadata...'
      service.
    end

    # Step 4: Upload VTT to Cloudflare if available (English + any translations)
    if @video.has_polished_vtt?
      Rails.logger.info '[VideoTranscriptionCompletionWorker] Uploading VTT captions to Cloudflare...'
      results = CloudflareVttService.new(@video).upload_all_vtt_captions
      Rails.logger.info "[VideoTranscriptionCompletionWorker] Uploaded #{results.count { |_, v| v }} VTT captions"
    end

    # Step 5: Mark as completed
    @video.update!(transcription_state: :completed, transcribed_at: Time.current)

    # Step 6: Generate content embeddings
    Rails.logger.info '[VideoTranscriptionCompletionWorker] Queueing embedding generation...'
    EmbeddingWorker.perform_async('Video', @video.id)

    # Step 7: Send email notification
    send_completion_notification

    Rails.logger.info "[VideoTranscriptionCompletionWorker] Completed processing Video #{video_id}"
  rescue StandardError => e
    @video.update!(transcription_state: :error)
    raise # AppSignal captures error details automatically
  end
end