@mux/ai 0.43.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3480,8 +3480,32 @@ async function hasBurnedInCaptionsInternal(assetId, options, collectedUsage) {
3480
3480
 
3481
3481
  // src/workflows/chapters.ts
3482
3482
  import { generateText as generateText3, Output as Output3 } from "ai";
3483
- import dedent4 from "dedent";
3483
+ import dedent5 from "dedent";
3484
3484
  import { z as z5 } from "zod";
3485
+
3486
+ // src/prompts/chapters.ts
3487
+ import dedent4 from "dedent";
3488
+ function createChapterGuidance({
3489
+ terminologySource = "transcript"
3490
+ } = {}) {
3491
+ return {
3492
+ qualityGuidelines: {
3493
+ tag: "quality_guidelines",
3494
+ content: dedent4`
3495
+ - Create chapters at topic shifts or clear transitions
3496
+ - Keep chapter titles concise and descriptive`
3497
+ },
3498
+ titleGuidelines: {
3499
+ tag: "title_guidelines",
3500
+ content: dedent4`
3501
+ - Keep titles concise and descriptive
3502
+ - Avoid filler or generic labels like "Chapter 1"
3503
+ ${terminologySource === "transcript" ? "- Use the transcript's terminology" : "- Use terminology from the provided evidence"}`
3504
+ }
3505
+ };
3506
+ }
3507
+
3508
+ // src/workflows/chapters.ts
3485
3509
  var chapterSchema = z5.object({
3486
3510
  startTime: z5.number(),
3487
3511
  title: z5.string().max(300)
@@ -3539,6 +3563,7 @@ async function generateChaptersWithAI({
3539
3563
  unexpectedChapterKeys
3540
3564
  };
3541
3565
  }
3566
+ var chapterGuidance = createChapterGuidance();
3542
3567
  var chapterSystemPromptBuilder = createPromptBuilder({
3543
3568
  template: {
3544
3569
  role: {
@@ -3547,13 +3572,13 @@ var chapterSystemPromptBuilder = createPromptBuilder({
3547
3572
  },
3548
3573
  context: {
3549
3574
  tag: "context",
3550
- content: dedent4`
3575
+ content: dedent5`
3551
3576
  You receive a timestamped transcript with lines in the form "[12s] Caption text".
3552
3577
  Use those timestamps as anchors to determine chapter start times in seconds.`
3553
3578
  },
3554
3579
  security: {
3555
3580
  tag: "security",
3556
- content: dedent4`
3581
+ content: dedent5`
3557
3582
  ${NON_DISCLOSURE_CONSTRAINT}
3558
3583
 
3559
3584
  ${UNTRUSTED_USER_INPUT_NOTICE}
@@ -3562,34 +3587,32 @@ var chapterSystemPromptBuilder = createPromptBuilder({
3562
3587
  },
3563
3588
  constraints: {
3564
3589
  tag: "constraints",
3565
- content: dedent4`
3590
+ content: dedent5`
3566
3591
  - Only use information present in the transcript
3567
3592
  - Return structured data that matches the requested JSON schema
3568
3593
  - Do not add commentary or extra text outside the JSON
3569
3594
  - When a <language> section is provided, all chapter titles MUST be written in that language`
3570
3595
  },
3571
3596
  qualityGuidelines: {
3572
- tag: "quality_guidelines",
3573
- content: dedent4`
3574
- - Create chapters at topic shifts or clear transitions
3575
- - Keep chapter titles concise and descriptive
3576
- - Ensure the first chapter starts at 0 seconds`
3597
+ ...chapterGuidance.qualityGuidelines,
3598
+ content: `${chapterGuidance.qualityGuidelines.content}
3599
+ - Ensure the first chapter starts at 0 seconds`
3577
3600
  }
3578
3601
  },
3579
3602
  sectionOrder: ["role", "context", "security", "constraints", "qualityGuidelines"]
3580
3603
  });
3581
3604
  var AUDIO_ONLY_SYSTEM_PROMPT_OVERRIDES = {
3582
3605
  role: "You are an audio editor and transcript analyst specializing in segmenting content into logical chapters.",
3583
- context: dedent4`
3606
+ context: dedent5`
3584
3607
  You receive a timestamped transcript from audio-only content with lines in the form "[12s] Transcript text".
3585
3608
  Use those timestamps as anchors to determine chapter start times in seconds.`
3586
3609
  };
3587
3610
  var SCENE_CONTEXT_SYSTEM_PROMPT_OVERRIDES = {
3588
- context: dedent4`
3611
+ context: dedent5`
3589
3612
  You receive a timestamped transcript with lines in the form "[12s] Caption text" and an ordered scene context.
3590
3613
  Transcript timestamps are in seconds. Scene start and end timestamps are in milliseconds.
3591
3614
  Use the scene progression to choose logical chapter groupings and scene starts as chapter boundaries.`,
3592
- constraints: dedent4`
3615
+ constraints: dedent5`
3593
3616
  - Only use information present in the transcript and scene context
3594
3617
  - Return structured data that matches the requested JSON schema
3595
3618
  - Do not add commentary or extra text outside the JSON
@@ -3603,7 +3626,7 @@ var chaptersPromptBuilder = createPromptBuilder({
3603
3626
  },
3604
3627
  outputFormat: {
3605
3628
  tag: "output_format",
3606
- content: dedent4`
3629
+ content: dedent5`
3607
3630
  Return valid JSON in this exact shape:
3608
3631
  {
3609
3632
  "chapters": [
@@ -3620,13 +3643,7 @@ var chaptersPromptBuilder = createPromptBuilder({
3620
3643
  content: ""
3621
3644
  // Placeholder - always overridden with dynamic content
3622
3645
  },
3623
- titleGuidelines: {
3624
- tag: "title_guidelines",
3625
- content: dedent4`
3626
- - Keep titles concise and descriptive
3627
- - Avoid filler or generic labels like "Chapter 1"
3628
- - Use the transcript's terminology`
3629
- }
3646
+ titleGuidelines: chapterGuidance.titleGuidelines
3630
3647
  },
3631
3648
  sectionOrder: ["task", "outputFormat", "chapterGuidelines", "titleGuidelines"]
3632
3649
  });
@@ -3665,7 +3682,7 @@ function buildUserPrompt3({
3665
3682
  } else if (scope) {
3666
3683
  firstChapterGuideline = `- The first chapter must start at ${scope.startTime}s`;
3667
3684
  }
3668
- const dynamicChapterGuidelines = dedent4`
3685
+ const dynamicChapterGuidelines = dedent5`
3669
3686
  - Create at least ${minChaptersPerHour} and at most ${maxChaptersPerHour} chapters per hour of content
3670
3687
  - Use start times in seconds (not HH:MM:SS)
3671
3688
  ${scope ? `- Analyze only the range from ${scope.startTime}s (inclusive) to ${scope.endTime}s (exclusive)` : ""}
@@ -5323,7 +5340,7 @@ async function generateVideoEmbeddings(assetId, options = {}) {
5323
5340
 
5324
5341
  // src/workflows/engagement-insights.ts
5325
5342
  import { generateText as generateText5, Output as Output5 } from "ai";
5326
- import dedent5 from "dedent";
5343
+ import dedent6 from "dedent";
5327
5344
  import { z as z7 } from "zod";
5328
5345
 
5329
5346
  // src/primitives/heatmap.ts
@@ -5592,7 +5609,7 @@ var AUDIO_ONLY_SYSTEM_PROMPT2 = promptDedent`
5592
5609
  - Connect engagement data to content features
5593
5610
  </quality_guidelines>
5594
5611
  `;
5595
- var INSIGHT_GUIDELINES = dedent5`
5612
+ var INSIGHT_GUIDELINES = dedent6`
5596
5613
  Provide explanatory insights that describe WHY moments are engaging.
5597
5614
  Focus on observable patterns and viewer behavior correlation.
5598
5615
  Example: "The cooking demonstration at 2:15 has 3x average engagement
@@ -5610,7 +5627,7 @@ var engagementInsightsPromptBuilder = createPromptBuilder({
5610
5627
  },
5611
5628
  outputFormat: {
5612
5629
  tag: "output_format",
5613
- content: dedent5`
5630
+ content: dedent6`
5614
5631
  Return valid JSON matching the provided schema.
5615
5632
  Include insights for each hotspot and overall engagement trends.
5616
5633
  Each momentInsight must include the hotspotIndex matching the input.
@@ -5618,7 +5635,7 @@ var engagementInsightsPromptBuilder = createPromptBuilder({
5618
5635
  },
5619
5636
  visualContext: {
5620
5637
  tag: "visual_context",
5621
- content: dedent5`
5638
+ content: dedent6`
5622
5639
  Images are provided for each hotspot timestamp.
5623
5640
  A storyboard overview image may also be included showing the full video timeline.
5624
5641
  Use visual evidence from these images to support your engagement analysis.
@@ -5632,14 +5649,14 @@ function buildUserPrompt4(hotspots, transcriptSegments, heatmap, isAudioOnly) {
5632
5649
  const transcript = transcriptSegments[idx]?.text || "(no transcript)";
5633
5650
  const startTimestamp = secondsToTimestamp(h.startMs / 1e3);
5634
5651
  const endTimestamp = secondsToTimestamp(h.endMs / 1e3);
5635
- return dedent5`
5652
+ return dedent6`
5636
5653
  Hotspot ${idx} (hotspotIndex: ${idx}):
5637
5654
  - Time Range: ${startTimestamp} - ${endTimestamp}
5638
5655
  - Engagement Score: ${h.score.toFixed(2)} (0=low, 1=high)
5639
5656
  - Transcript: ${JSON.stringify(transcript)}
5640
5657
  `;
5641
5658
  }).join("\n\n");
5642
- const heatmapData = dedent5`
5659
+ const heatmapData = dedent6`
5643
5660
  Engagement Heatmap (${heatmap.length} values, each representing 1/${heatmap.length}th of the video, higher = more re-watches):
5644
5661
  [${heatmap.map((v) => v.toFixed(2)).join(", ")}]
5645
5662
  `;
@@ -7458,7 +7475,6 @@ async function getModerationScores(assetId, options = {}) {
7458
7475
 
7459
7476
  // src/workflows/summarization.ts
7460
7477
  import { generateText as generateText7, Output as Output7 } from "ai";
7461
- import dedent6 from "dedent";
7462
7478
  import { z as z9 } from "zod";
7463
7479
 
7464
7480
  // src/lib/markdown-normalization.ts
@@ -7468,124 +7484,128 @@ function normalizeMarkdownDescription(description) {
7468
7484
  return description.replace(ESCAPED_LINE_BREAK_REGEX, "\n").replace(/([^\n]) {2,}([*-]) (?=\S)/g, "$1\n$2 ").replace(/([.!?:;]) ([*-]) (?=\S)/g, "$1\n$2 ").replace(MULTIPLE_BLANK_LINES_REGEX, "\n\n");
7469
7485
  }
7470
7486
 
7471
- // src/workflows/summarization.ts
7487
+ // src/prompts/summarization.ts
7488
+ import dedent7 from "dedent";
7472
7489
  var DEFAULT_SUMMARY_KEYWORD_LIMIT = 10;
7473
7490
  var DEFAULT_TITLE_LENGTH = 10;
7474
7491
  var DEFAULT_DESCRIPTION_LENGTH = 50;
7475
- var summarySchema = z9.object({
7476
- keywords: z9.array(z9.string().max(200)),
7477
- title: z9.string().max(500),
7478
- description: z9.string().max(1e4)
7479
- });
7480
- function buildSummarySchema(descriptionLength) {
7481
- const descriptionMaxChars = Math.max(2e3, descriptionLength * 15);
7482
- return z9.object({
7483
- keywords: z9.array(z9.string().max(200)),
7484
- title: z9.string().max(500),
7485
- description: z9.string().max(descriptionMaxChars)
7486
- });
7487
- }
7488
- var VALID_TONES = ["neutral", "playful", "professional"];
7489
- var TONE_INSTRUCTIONS = {
7490
- neutral: "Provide a clear, straightforward analysis.",
7491
- playful: "Channel your inner diva! Answer with maximum sass, wit, and playful attitude. Don't hold back - be cheeky, clever, and delightfully snarky. Make it pop!",
7492
- professional: "Provide a professional, executive-level analysis suitable for business reporting."
7493
- };
7494
7492
  var DESCRIPTION_LENGTH_THRESHOLD_SMALL = 25;
7495
7493
  var DESCRIPTION_LENGTH_THRESHOLD_LARGE = 100;
7496
7494
  function buildDescriptionGuidance(wordCount, contentType) {
7497
7495
  if (wordCount < DESCRIPTION_LENGTH_THRESHOLD_SMALL) {
7498
7496
  if (contentType === "video") {
7499
- return dedent6`A brief summary of the video in no more than ${wordCount} words. Shorter is fine.
7497
+ return dedent7`A brief summary of the video in no more than ${wordCount} words. Shorter is fine.
7500
7498
  Focus on the single most important subject or action.
7501
7499
  Write in present tense.`;
7502
7500
  }
7503
- return dedent6`A brief summary of the audio content in no more than ${wordCount} words. Shorter is fine.
7501
+ return dedent7`A brief summary of the audio content in no more than ${wordCount} words. Shorter is fine.
7504
7502
  Focus on the single most important topic or theme.
7505
7503
  Write in present tense.`;
7506
7504
  }
7507
7505
  if (wordCount > DESCRIPTION_LENGTH_THRESHOLD_LARGE) {
7508
7506
  if (contentType === "video") {
7509
- return dedent6`A detailed summary that describes what happens across the video.
7507
+ return dedent7`A detailed summary that describes what happens across the video.
7510
7508
  Never exceed ${wordCount} words, but shorter is perfectly fine. You may use multiple sentences.
7511
7509
  Be thorough: cover subjects, actions, setting, progression, and any notable details visible across frames.
7512
7510
  Write in present tense. Be specific about observable details rather than making assumptions.
7513
7511
  If the transcript provides dialogue or narration, incorporate key points but prioritize visual content.`;
7514
7512
  }
7515
- return dedent6`A detailed summary that describes the audio content.
7513
+ return dedent7`A detailed summary that describes the audio content.
7516
7514
  Never exceed ${wordCount} words, but shorter is perfectly fine. You may use multiple sentences.
7517
7515
  Be thorough: cover topics, speakers, themes, progression, and any notable insights.
7518
7516
  Write in present tense. Be specific about what is discussed or presented rather than making assumptions.
7519
7517
  Focus on the spoken content and any key insights, dialogue, or narrative elements.`;
7520
7518
  }
7521
7519
  if (contentType === "video") {
7522
- return dedent6`A summary that describes what happens across the video.
7520
+ return dedent7`A summary that describes what happens across the video.
7523
7521
  Never exceed ${wordCount} words, but shorter is perfectly fine. You may use multiple sentences.
7524
7522
  Cover the main subjects, actions, setting, and any notable progression visible across frames.
7525
7523
  Write in present tense. Be specific about observable details rather than making assumptions.
7526
7524
  If the transcript provides dialogue or narration, incorporate key points but prioritize visual content.`;
7527
7525
  }
7528
- return dedent6`A summary that describes the audio content.
7526
+ return dedent7`A summary that describes the audio content.
7529
7527
  Never exceed ${wordCount} words, but shorter is perfectly fine. You may use multiple sentences.
7530
7528
  Cover the main topics, speakers, themes, and any notable progression in the discussion or narration.
7531
7529
  Write in present tense. Be specific about what is discussed or presented rather than making assumptions.
7532
7530
  Focus on the spoken content and any key insights, dialogue, or narrative elements.`;
7533
7531
  }
7534
- function buildSceneAwareDescriptionGuidance(wordCount) {
7532
+ function buildSceneAwareDescriptionGuidance(wordCount, hasStoryboard) {
7533
+ const storyboardGuidance = hasStoryboard ? "Use the storyboard as direct visual evidence and the scene context to preserve progression." : "Use the ordered scene context as grounded evidence of the content and its progression.";
7535
7534
  if (wordCount < DESCRIPTION_LENGTH_THRESHOLD_SMALL) {
7536
- return dedent6`A brief summary of the video in no more than ${wordCount} words. Shorter is fine.
7535
+ return dedent7`A brief summary of the video in no more than ${wordCount} words. Shorter is fine.
7537
7536
  Focus on the single most important subject or action across the ordered scenes.
7538
- Use the storyboard as direct visual evidence and the scene context to preserve progression.
7537
+ ${storyboardGuidance}
7539
7538
  Write in present tense.`;
7540
7539
  }
7541
7540
  if (wordCount > DESCRIPTION_LENGTH_THRESHOLD_LARGE) {
7542
- return dedent6`A detailed summary that describes what happens across the ordered scenes.
7541
+ return dedent7`A detailed summary that describes what happens across the ordered scenes.
7543
7542
  Never exceed ${wordCount} words, but shorter is perfectly fine. You may use multiple sentences.
7544
7543
  Be thorough: cover subjects, actions, setting, progression, and notable details supported across scenes.
7545
- Use the storyboard as direct visual evidence and the scene context to preserve progression.
7544
+ ${storyboardGuidance}
7546
7545
  Write in present tense. If the transcript provides dialogue or narration, incorporate key points while preserving scene progression.`;
7547
7546
  }
7548
- return dedent6`A summary that describes what happens across the ordered scenes.
7547
+ return dedent7`A summary that describes what happens across the ordered scenes.
7549
7548
  Never exceed ${wordCount} words, but shorter is perfectly fine. You may use multiple sentences.
7550
7549
  Cover the main subjects, actions, setting, and notable progression supported across scenes.
7551
- Use the storyboard as direct visual evidence and the scene context to preserve progression.
7550
+ ${storyboardGuidance}
7552
7551
  Write in present tense. If the transcript provides dialogue or narration, incorporate key points while preserving scene progression.`;
7553
7552
  }
7554
- function createSummarizationBuilder({ titleLength, descriptionLength, tagCount } = {}, { hasSceneContext = false } = {}) {
7553
+ function createSummarizationGuidance({
7554
+ mediaType = "video",
7555
+ titleLength,
7556
+ descriptionLength,
7557
+ tagCount,
7558
+ hasSceneContext = false,
7559
+ hasStoryboard = true
7560
+ } = {}) {
7555
7561
  const titleLimit = titleLength ?? DEFAULT_TITLE_LENGTH;
7562
+ const descriptionLimit = descriptionLength ?? DEFAULT_DESCRIPTION_LENGTH;
7556
7563
  const keywordLimit = tagCount ?? DEFAULT_SUMMARY_KEYWORD_LIMIT;
7557
- const task = hasSceneContext ? "Analyze the storyboard frames and ordered scene context together, then generate metadata that captures the full progression of the video content." : "Analyze the storyboard frames and generate metadata that captures the essence of the video content.";
7558
- const qualityGuidelines = hasSceneContext ? dedent6`
7559
- - Follow scene_index order to understand what begins, develops, and concludes
7560
- - Use scene narratives and concepts as grounded evidence, preserving consistent terminology across the output
7561
- - Use the storyboard as direct visual evidence for whole-asset details
7562
- - Balance brevity with informativeness` : dedent6`
7563
- - Examine all frames to understand the full context and progression
7564
- - Be precise: "golden retriever" is better than "dog" when identifiable
7565
- - Capture the narrative: what begins, develops, and concludes
7566
- - Balance brevity with informativeness`;
7567
- return createPromptBuilder({
7568
- template: {
7569
- task: {
7570
- tag: "task",
7571
- content: task
7572
- },
7573
- title: {
7574
- tag: "title_requirements",
7575
- content: dedent6`
7564
+ const isAudioOnly = mediaType === "audio";
7565
+ const sceneAware = !isAudioOnly && hasSceneContext;
7566
+ const qualityGuidelines = isAudioOnly ? dedent7`
7567
+ - Analyze the full transcript to understand context and themes
7568
+ - Be precise: use specific terminology when mentioned
7569
+ - Capture the narrative: what is introduced, discussed, and concluded
7570
+ - Balance brevity with informativeness` : sceneAware ? dedent7`
7571
+ - Follow scene_index order to understand what begins, develops, and concludes
7572
+ - Use scene narratives and concepts as grounded evidence, preserving consistent terminology across the output
7573
+ ${hasStoryboard ? "- Use the storyboard as direct visual evidence for whole-asset details" : "- Ground whole-asset details in the provided scene context and transcript when available"}
7574
+ - Balance brevity with informativeness` : dedent7`
7575
+ - Examine all frames to understand the full context and progression
7576
+ - Be precise: "golden retriever" is better than "dog" when identifiable
7577
+ - Capture the narrative: what begins, develops, and concludes
7578
+ - Balance brevity with informativeness`;
7579
+ return {
7580
+ title: {
7581
+ tag: "title_requirements",
7582
+ content: isAudioOnly ? dedent7`
7583
+ A concise, label-style title — not a sentence or description.
7584
+ Never exceed ${titleLimit} words, but shorter is better.
7585
+ Think of how a podcast episode title or playlist entry would read — e.g. "Weekly News Roundup" or "Interview with Dr. Smith".
7586
+ Start with the primary subject or topic. Never begin with "An audio of" or similar phrasing.
7587
+ Use specific nouns over lengthy descriptions. Avoid clauses, conjunctions, or narrative structure.` : dedent7`
7576
7588
  A concise, label-style title — not a sentence or description.
7577
7589
  Never exceed ${titleLimit} words, but shorter is better.
7578
7590
  Think of how a video card title, playlist entry, or file name would read — e.g. "Predator: Badlands Trailer" or "Chef Prepares Holiday Feast".
7579
7591
  Start with the primary subject or topic. Never begin with "A video of" or similar phrasing.
7580
7592
  Use specific nouns over lengthy descriptions. Avoid clauses, conjunctions, or narrative structure.`
7581
- },
7582
- description: {
7583
- tag: "description_requirements",
7584
- content: hasSceneContext ? buildSceneAwareDescriptionGuidance(descriptionLength ?? DEFAULT_DESCRIPTION_LENGTH) : buildDescriptionGuidance(descriptionLength ?? DEFAULT_DESCRIPTION_LENGTH, "video")
7585
- },
7586
- keywords: {
7587
- tag: "keywords_requirements",
7588
- content: dedent6`
7593
+ },
7594
+ description: {
7595
+ tag: "description_requirements",
7596
+ content: sceneAware ? buildSceneAwareDescriptionGuidance(descriptionLimit, hasStoryboard) : buildDescriptionGuidance(descriptionLimit, mediaType)
7597
+ },
7598
+ keywords: {
7599
+ tag: "keywords_requirements",
7600
+ content: isAudioOnly ? dedent7`
7601
+ Specific, searchable terms (up to ${keywordLimit}) that capture:
7602
+ - Primary topics and themes
7603
+ - Speakers or presenters (if named)
7604
+ - Key concepts and terminology
7605
+ - Content type (interview, lecture, music, etc.)
7606
+ - Genre or style (if applicable)
7607
+ Prefer concrete nouns and relevant terms over abstract concepts.
7608
+ Use lowercase. Avoid redundant or overly generic terms like "audio" or "content".` : dedent7`
7589
7609
  Specific, searchable terms (up to ${keywordLimit}) that capture:
7590
7610
  - Primary subjects (people, animals, objects)
7591
7611
  - Actions and activities being performed
@@ -7594,57 +7614,51 @@ function createSummarizationBuilder({ titleLength, descriptionLength, tagCount }
7594
7614
  - Style or genre (if applicable)
7595
7615
  Prefer concrete nouns and action verbs over abstract concepts.
7596
7616
  Use lowercase. Avoid redundant or overly generic terms like "video" or "content".`
7617
+ },
7618
+ qualityGuidelines: { tag: "quality_guidelines", content: qualityGuidelines }
7619
+ };
7620
+ }
7621
+
7622
+ // src/workflows/summarization.ts
7623
+ var summarySchema = z9.object({
7624
+ keywords: z9.array(z9.string().max(200)),
7625
+ title: z9.string().max(500),
7626
+ description: z9.string().max(1e4)
7627
+ });
7628
+ function buildSummarySchema(descriptionLength) {
7629
+ const descriptionMaxChars = Math.max(2e3, descriptionLength * 15);
7630
+ return z9.object({
7631
+ keywords: z9.array(z9.string().max(200)),
7632
+ title: z9.string().max(500),
7633
+ description: z9.string().max(descriptionMaxChars)
7634
+ });
7635
+ }
7636
+ var VALID_TONES = ["neutral", "playful", "professional"];
7637
+ var TONE_INSTRUCTIONS = {
7638
+ neutral: "Provide a clear, straightforward analysis.",
7639
+ playful: "Channel your inner diva! Answer with maximum sass, wit, and playful attitude. Don't hold back - be cheeky, clever, and delightfully snarky. Make it pop!",
7640
+ professional: "Provide a professional, executive-level analysis suitable for business reporting."
7641
+ };
7642
+ function createSummarizationBuilder(constraints = {}, { hasSceneContext = false } = {}) {
7643
+ return createPromptBuilder({
7644
+ template: {
7645
+ task: {
7646
+ tag: "task",
7647
+ content: hasSceneContext ? "Analyze the storyboard frames and ordered scene context together, then generate metadata that captures the full progression of the video content." : "Analyze the storyboard frames and generate metadata that captures the essence of the video content."
7597
7648
  },
7598
- qualityGuidelines: {
7599
- tag: "quality_guidelines",
7600
- content: qualityGuidelines
7601
- }
7649
+ ...createSummarizationGuidance({ ...constraints, hasSceneContext })
7602
7650
  },
7603
7651
  sectionOrder: ["task", "title", "description", "keywords", "qualityGuidelines"]
7604
7652
  });
7605
7653
  }
7606
- function createAudioOnlyBuilder({ titleLength, descriptionLength, tagCount } = {}) {
7607
- const titleLimit = titleLength ?? DEFAULT_TITLE_LENGTH;
7608
- const keywordLimit = tagCount ?? DEFAULT_SUMMARY_KEYWORD_LIMIT;
7654
+ function createAudioOnlyBuilder(constraints = {}) {
7609
7655
  return createPromptBuilder({
7610
7656
  template: {
7611
7657
  task: {
7612
7658
  tag: "task",
7613
7659
  content: "Analyze the transcript and generate metadata that captures the essence of the audio content."
7614
7660
  },
7615
- title: {
7616
- tag: "title_requirements",
7617
- content: dedent6`
7618
- A concise, label-style title — not a sentence or description.
7619
- Never exceed ${titleLimit} words, but shorter is better.
7620
- Think of how a podcast episode title or playlist entry would read — e.g. "Weekly News Roundup" or "Interview with Dr. Smith".
7621
- Start with the primary subject or topic. Never begin with "An audio of" or similar phrasing.
7622
- Use specific nouns over lengthy descriptions. Avoid clauses, conjunctions, or narrative structure.`
7623
- },
7624
- description: {
7625
- tag: "description_requirements",
7626
- content: buildDescriptionGuidance(descriptionLength ?? DEFAULT_DESCRIPTION_LENGTH, "audio")
7627
- },
7628
- keywords: {
7629
- tag: "keywords_requirements",
7630
- content: dedent6`
7631
- Specific, searchable terms (up to ${keywordLimit}) that capture:
7632
- - Primary topics and themes
7633
- - Speakers or presenters (if named)
7634
- - Key concepts and terminology
7635
- - Content type (interview, lecture, music, etc.)
7636
- - Genre or style (if applicable)
7637
- Prefer concrete nouns and relevant terms over abstract concepts.
7638
- Use lowercase. Avoid redundant or overly generic terms like "audio" or "content".`
7639
- },
7640
- qualityGuidelines: {
7641
- tag: "quality_guidelines",
7642
- content: dedent6`
7643
- - Analyze the full transcript to understand context and themes
7644
- - Be precise: use specific terminology when mentioned
7645
- - Capture the narrative: what is introduced, discussed, and concluded
7646
- - Balance brevity with informativeness`
7647
- }
7661
+ ...createSummarizationGuidance({ ...constraints, mediaType: "audio" })
7648
7662
  },
7649
7663
  sectionOrder: ["task", "title", "description", "keywords", "qualityGuidelines"]
7650
7664
  });