Class: YouTube::DescriptionService

Inherits:
Object
  • Object
show all
Defined in:
app/services/youtube/description_service.rb

Overview

Generates an SEO/YouTube-friendly expanded description from a structured
transcript using AssemblyAI's LLM Gateway. The result is plain text — a
hook, 3-5 emoji bullet points, a soft CTA, and 1-3 hashtags — and is
written into Video#expanded_description (the local field used by the
public site, schema.org JSON-LD, OG tags, and the YouTube push flow).

Constant Summary collapse

BULLET_COUNT_MIN =
3
BULLET_COUNT_MAX =
5
HOOK_MAX_CHARS =
200
BULLET_TEXT_MAX =
160
HASHTAG_MAX =
3
LLM_MAX_TOKENS =
1024
DESCRIPTION_TOOL_NAME =
'youtube_seo_description'
TRANSCRIPT_CHARS_MAX =
8000

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeDescriptionService

Returns a new instance of DescriptionService.



21
22
23
24
# File 'app/services/youtube/description_service.rb', line 21

def initialize
  @logger = Rails.logger
  @preview_failure_message = nil
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



19
20
21
# File 'app/services/youtube/description_service.rb', line 19

def logger
  @logger
end

#preview_failure_messageObject (readonly)

Returns the value of attribute preview_failure_message.



19
20
21
# File 'app/services/youtube/description_service.rb', line 19

def preview_failure_message
  @preview_failure_message
end

Instance Method Details

#generate_description(video) ⇒ String?

Generate a description from the video's transcript paragraphs.

Parameters:

Returns:

  • (String, nil)

    the assembled description, or nil if generation failed



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/services/youtube/description_service.rb', line 29

def generate_description(video)
  @preview_failure_message = nil
  paragraphs = video.structured_transcript_paragraphs
  if paragraphs.blank?
    @preview_failure_message = 'No transcript paragraphs in structured transcript.'
    return nil
  end

  raw = fetch_description_proposal(video, paragraphs)
  assembled = assemble_description(raw)
  if assembled.blank?
    @preview_failure_message ||= 'LLM returned an empty or unusable description.'
    return nil
  end

  assembled
rescue StandardError => e
  logger.error("[YouTube::DescriptionService] Description LLM call failed: #{e.message}")
  @preview_failure_message = "LLM call failed: #{e.message.to_s.truncate(200)}"
  nil
end