vidpipe 1.0.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.
- package/README.md +243 -0
- package/assets/fonts/Montserrat-Bold.ttf +0 -0
- package/assets/fonts/Montserrat-Regular.ttf +0 -0
- package/assets/fonts/OFL.txt +93 -0
- package/dist/__tests__/agents.test.d.ts +2 -0
- package/dist/__tests__/agents.test.d.ts.map +1 -0
- package/dist/__tests__/agents.test.js +434 -0
- package/dist/__tests__/agents.test.js.map +1 -0
- package/dist/__tests__/aspectRatio.test.d.ts +2 -0
- package/dist/__tests__/aspectRatio.test.d.ts.map +1 -0
- package/dist/__tests__/aspectRatio.test.js +406 -0
- package/dist/__tests__/aspectRatio.test.js.map +1 -0
- package/dist/__tests__/captionGenerator.test.d.ts +2 -0
- package/dist/__tests__/captionGenerator.test.d.ts.map +1 -0
- package/dist/__tests__/captionGenerator.test.js +435 -0
- package/dist/__tests__/captionGenerator.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +81 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/faceDetection.test.d.ts +2 -0
- package/dist/__tests__/faceDetection.test.d.ts.map +1 -0
- package/dist/__tests__/faceDetection.test.js +372 -0
- package/dist/__tests__/faceDetection.test.js.map +1 -0
- package/dist/__tests__/ffmpegTools.test.d.ts +2 -0
- package/dist/__tests__/ffmpegTools.test.d.ts.map +1 -0
- package/dist/__tests__/ffmpegTools.test.js +464 -0
- package/dist/__tests__/ffmpegTools.test.js.map +1 -0
- package/dist/__tests__/integration/captionBurn.test.d.ts +2 -0
- package/dist/__tests__/integration/captionBurn.test.d.ts.map +1 -0
- package/dist/__tests__/integration/captionBurn.test.js +103 -0
- package/dist/__tests__/integration/captionBurn.test.js.map +1 -0
- package/dist/__tests__/integration/clipComposite.test.d.ts +2 -0
- package/dist/__tests__/integration/clipComposite.test.d.ts.map +1 -0
- package/dist/__tests__/integration/clipComposite.test.js +56 -0
- package/dist/__tests__/integration/clipComposite.test.js.map +1 -0
- package/dist/__tests__/integration/faceDetection.test.d.ts +2 -0
- package/dist/__tests__/integration/faceDetection.test.d.ts.map +1 -0
- package/dist/__tests__/integration/faceDetection.test.js +85 -0
- package/dist/__tests__/integration/faceDetection.test.js.map +1 -0
- package/dist/__tests__/integration/ffmpegPipeline.test.d.ts +2 -0
- package/dist/__tests__/integration/ffmpegPipeline.test.d.ts.map +1 -0
- package/dist/__tests__/integration/ffmpegPipeline.test.js +88 -0
- package/dist/__tests__/integration/ffmpegPipeline.test.js.map +1 -0
- package/dist/__tests__/integration/fixture.d.ts +19 -0
- package/dist/__tests__/integration/fixture.d.ts.map +1 -0
- package/dist/__tests__/integration/fixture.js +112 -0
- package/dist/__tests__/integration/fixture.js.map +1 -0
- package/dist/__tests__/integration/fixture.test.d.ts +2 -0
- package/dist/__tests__/integration/fixture.test.d.ts.map +1 -0
- package/dist/__tests__/integration/fixture.test.js +27 -0
- package/dist/__tests__/integration/fixture.test.js.map +1 -0
- package/dist/__tests__/integration/realCaptions.test.d.ts +2 -0
- package/dist/__tests__/integration/realCaptions.test.d.ts.map +1 -0
- package/dist/__tests__/integration/realCaptions.test.js +226 -0
- package/dist/__tests__/integration/realCaptions.test.js.map +1 -0
- package/dist/__tests__/integration/realPipeline.test.d.ts +2 -0
- package/dist/__tests__/integration/realPipeline.test.d.ts.map +1 -0
- package/dist/__tests__/integration/realPipeline.test.js +210 -0
- package/dist/__tests__/integration/realPipeline.test.js.map +1 -0
- package/dist/__tests__/integration/silenceRemoval.test.d.ts +2 -0
- package/dist/__tests__/integration/silenceRemoval.test.d.ts.map +1 -0
- package/dist/__tests__/integration/silenceRemoval.test.js +93 -0
- package/dist/__tests__/integration/silenceRemoval.test.js.map +1 -0
- package/dist/__tests__/pipeline.test.d.ts +2 -0
- package/dist/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline.test.js +434 -0
- package/dist/__tests__/pipeline.test.js.map +1 -0
- package/dist/__tests__/services.test.d.ts +2 -0
- package/dist/__tests__/services.test.d.ts.map +1 -0
- package/dist/__tests__/services.test.js +655 -0
- package/dist/__tests__/services.test.js.map +1 -0
- package/dist/__tests__/silenceRemoval.test.d.ts +2 -0
- package/dist/__tests__/silenceRemoval.test.d.ts.map +1 -0
- package/dist/__tests__/silenceRemoval.test.js +266 -0
- package/dist/__tests__/silenceRemoval.test.js.map +1 -0
- package/dist/__tests__/singlePassEdit.test.d.ts +2 -0
- package/dist/__tests__/singlePassEdit.test.d.ts.map +1 -0
- package/dist/__tests__/singlePassEdit.test.js +321 -0
- package/dist/__tests__/singlePassEdit.test.js.map +1 -0
- package/dist/__tests__/smoke.test.d.ts +2 -0
- package/dist/__tests__/smoke.test.d.ts.map +1 -0
- package/dist/__tests__/smoke.test.js +8 -0
- package/dist/__tests__/smoke.test.js.map +1 -0
- package/dist/__tests__/utilities.test.d.ts +2 -0
- package/dist/__tests__/utilities.test.d.ts.map +1 -0
- package/dist/__tests__/utilities.test.js +268 -0
- package/dist/__tests__/utilities.test.js.map +1 -0
- package/dist/agents/BaseAgent.d.ts +52 -0
- package/dist/agents/BaseAgent.d.ts.map +1 -0
- package/dist/agents/BaseAgent.js +108 -0
- package/dist/agents/BaseAgent.js.map +1 -0
- package/dist/agents/BlogAgent.d.ts +3 -0
- package/dist/agents/BlogAgent.d.ts.map +1 -0
- package/dist/agents/BlogAgent.js +163 -0
- package/dist/agents/BlogAgent.js.map +1 -0
- package/dist/agents/ChapterAgent.d.ts +11 -0
- package/dist/agents/ChapterAgent.d.ts.map +1 -0
- package/dist/agents/ChapterAgent.js +191 -0
- package/dist/agents/ChapterAgent.js.map +1 -0
- package/dist/agents/MediumVideoAgent.d.ts +3 -0
- package/dist/agents/MediumVideoAgent.d.ts.map +1 -0
- package/dist/agents/MediumVideoAgent.js +219 -0
- package/dist/agents/MediumVideoAgent.js.map +1 -0
- package/dist/agents/ShortsAgent.d.ts +3 -0
- package/dist/agents/ShortsAgent.d.ts.map +1 -0
- package/dist/agents/ShortsAgent.js +243 -0
- package/dist/agents/ShortsAgent.js.map +1 -0
- package/dist/agents/SilenceRemovalAgent.d.ts +9 -0
- package/dist/agents/SilenceRemovalAgent.d.ts.map +1 -0
- package/dist/agents/SilenceRemovalAgent.js +208 -0
- package/dist/agents/SilenceRemovalAgent.js.map +1 -0
- package/dist/agents/SocialMediaAgent.d.ts +4 -0
- package/dist/agents/SocialMediaAgent.d.ts.map +1 -0
- package/dist/agents/SocialMediaAgent.js +248 -0
- package/dist/agents/SocialMediaAgent.js.map +1 -0
- package/dist/agents/SummaryAgent.d.ts +11 -0
- package/dist/agents/SummaryAgent.d.ts.map +1 -0
- package/dist/agents/SummaryAgent.js +333 -0
- package/dist/agents/SummaryAgent.js.map +1 -0
- package/dist/config/brand.d.ts +29 -0
- package/dist/config/brand.d.ts.map +1 -0
- package/dist/config/brand.js +83 -0
- package/dist/config/brand.js.map +1 -0
- package/dist/config/environment.d.ts +36 -0
- package/dist/config/environment.d.ts.map +1 -0
- package/dist/config/environment.js +44 -0
- package/dist/config/environment.js.map +1 -0
- package/dist/config/logger.d.ts +5 -0
- package/dist/config/logger.d.ts.map +1 -0
- package/dist/config/logger.js +13 -0
- package/dist/config/logger.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +135 -0
- package/dist/index.js.map +1 -0
- package/dist/pipeline.d.ts +57 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +287 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/services/captionGeneration.d.ts +7 -0
- package/dist/services/captionGeneration.d.ts.map +1 -0
- package/dist/services/captionGeneration.js +29 -0
- package/dist/services/captionGeneration.js.map +1 -0
- package/dist/services/fileWatcher.d.ts +19 -0
- package/dist/services/fileWatcher.d.ts.map +1 -0
- package/dist/services/fileWatcher.js +120 -0
- package/dist/services/fileWatcher.js.map +1 -0
- package/dist/services/gitOperations.d.ts +3 -0
- package/dist/services/gitOperations.d.ts.map +1 -0
- package/dist/services/gitOperations.js +43 -0
- package/dist/services/gitOperations.js.map +1 -0
- package/dist/services/socialPosting.d.ts +38 -0
- package/dist/services/socialPosting.d.ts.map +1 -0
- package/dist/services/socialPosting.js +102 -0
- package/dist/services/socialPosting.js.map +1 -0
- package/dist/services/transcription.d.ts +3 -0
- package/dist/services/transcription.d.ts.map +1 -0
- package/dist/services/transcription.js +100 -0
- package/dist/services/transcription.js.map +1 -0
- package/dist/services/videoIngestion.d.ts +3 -0
- package/dist/services/videoIngestion.d.ts.map +1 -0
- package/dist/services/videoIngestion.js +103 -0
- package/dist/services/videoIngestion.js.map +1 -0
- package/dist/tools/captions/captionGenerator.d.ts +84 -0
- package/dist/tools/captions/captionGenerator.d.ts.map +1 -0
- package/dist/tools/captions/captionGenerator.js +390 -0
- package/dist/tools/captions/captionGenerator.js.map +1 -0
- package/dist/tools/ffmpeg/aspectRatio.d.ts +101 -0
- package/dist/tools/ffmpeg/aspectRatio.d.ts.map +1 -0
- package/dist/tools/ffmpeg/aspectRatio.js +338 -0
- package/dist/tools/ffmpeg/aspectRatio.js.map +1 -0
- package/dist/tools/ffmpeg/audioExtraction.d.ts +16 -0
- package/dist/tools/ffmpeg/audioExtraction.d.ts.map +1 -0
- package/dist/tools/ffmpeg/audioExtraction.js +86 -0
- package/dist/tools/ffmpeg/audioExtraction.js.map +1 -0
- package/dist/tools/ffmpeg/captionBurning.d.ts +8 -0
- package/dist/tools/ffmpeg/captionBurning.d.ts.map +1 -0
- package/dist/tools/ffmpeg/captionBurning.js +71 -0
- package/dist/tools/ffmpeg/captionBurning.js.map +1 -0
- package/dist/tools/ffmpeg/clipExtraction.d.ts +23 -0
- package/dist/tools/ffmpeg/clipExtraction.d.ts.map +1 -0
- package/dist/tools/ffmpeg/clipExtraction.js +178 -0
- package/dist/tools/ffmpeg/clipExtraction.js.map +1 -0
- package/dist/tools/ffmpeg/faceDetection.d.ts +127 -0
- package/dist/tools/ffmpeg/faceDetection.d.ts.map +1 -0
- package/dist/tools/ffmpeg/faceDetection.js +500 -0
- package/dist/tools/ffmpeg/faceDetection.js.map +1 -0
- package/dist/tools/ffmpeg/frameCapture.d.ts +10 -0
- package/dist/tools/ffmpeg/frameCapture.d.ts.map +1 -0
- package/dist/tools/ffmpeg/frameCapture.js +48 -0
- package/dist/tools/ffmpeg/frameCapture.js.map +1 -0
- package/dist/tools/ffmpeg/silenceDetection.d.ts +10 -0
- package/dist/tools/ffmpeg/silenceDetection.d.ts.map +1 -0
- package/dist/tools/ffmpeg/silenceDetection.js +55 -0
- package/dist/tools/ffmpeg/silenceDetection.js.map +1 -0
- package/dist/tools/ffmpeg/singlePassEdit.d.ts +25 -0
- package/dist/tools/ffmpeg/singlePassEdit.d.ts.map +1 -0
- package/dist/tools/ffmpeg/singlePassEdit.js +123 -0
- package/dist/tools/ffmpeg/singlePassEdit.js.map +1 -0
- package/dist/tools/search/exaClient.d.ts +8 -0
- package/dist/tools/search/exaClient.d.ts.map +1 -0
- package/dist/tools/search/exaClient.js +38 -0
- package/dist/tools/search/exaClient.js.map +1 -0
- package/dist/tools/whisper/whisperClient.d.ts +3 -0
- package/dist/tools/whisper/whisperClient.d.ts.map +1 -0
- package/dist/tools/whisper/whisperClient.js +77 -0
- package/dist/tools/whisper/whisperClient.js.map +1 -0
- package/dist/types/index.d.ts +305 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +44 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import ffmpeg from 'fluent-ffmpeg';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { BaseAgent } from './BaseAgent';
|
|
4
|
+
import { detectSilence } from '../tools/ffmpeg/silenceDetection';
|
|
5
|
+
import { singlePassEdit } from '../tools/ffmpeg/singlePassEdit';
|
|
6
|
+
import logger from '../config/logger';
|
|
7
|
+
const ffmpegPath = process.env.FFMPEG_PATH || 'ffmpeg';
|
|
8
|
+
const ffprobePath = process.env.FFPROBE_PATH || 'ffprobe';
|
|
9
|
+
ffmpeg.setFfmpegPath(ffmpegPath);
|
|
10
|
+
ffmpeg.setFfprobePath(ffprobePath);
|
|
11
|
+
// ── System prompt ───────────────────────────────────────────────────────────
|
|
12
|
+
const SYSTEM_PROMPT = `You are a video editor AI that decides which silent regions in a video should be removed.
|
|
13
|
+
You will receive a transcript with timestamps and a list of detected silence regions.
|
|
14
|
+
|
|
15
|
+
Be CONSERVATIVE. Only remove silence that is CLEARLY dead air — no speech, no demonstration, no purpose.
|
|
16
|
+
Aim to remove no more than 10-15% of total video duration.
|
|
17
|
+
When in doubt, KEEP the silence.
|
|
18
|
+
|
|
19
|
+
KEEP silences that are:
|
|
20
|
+
- Dramatic pauses after impactful statements
|
|
21
|
+
- Brief thinking pauses (< 2 seconds) in natural speech
|
|
22
|
+
- Pauses before important reveals or demonstrations
|
|
23
|
+
- Pauses where the speaker is clearly showing something on screen
|
|
24
|
+
- Silence during screen demonstrations or typing — the viewer is watching the screen
|
|
25
|
+
|
|
26
|
+
REMOVE silences that are:
|
|
27
|
+
- Dead air with no purpose (> 3 seconds of nothing)
|
|
28
|
+
- Gaps between topics where the speaker was gathering thoughts
|
|
29
|
+
- Silence at the very beginning or end of the video
|
|
30
|
+
|
|
31
|
+
Return a JSON array of silence regions to REMOVE (not keep).
|
|
32
|
+
When you have decided, call the **decide_removals** tool with your removal list.`;
|
|
33
|
+
// ── JSON Schema for the decide_removals tool ────────────────────────────────
|
|
34
|
+
const DECIDE_REMOVALS_SCHEMA = {
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
removals: {
|
|
38
|
+
type: 'array',
|
|
39
|
+
description: 'Array of silence regions to remove',
|
|
40
|
+
items: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
properties: {
|
|
43
|
+
start: { type: 'number', description: 'Start time in seconds' },
|
|
44
|
+
end: { type: 'number', description: 'End time in seconds' },
|
|
45
|
+
reason: { type: 'string', description: 'Why this silence should be removed' },
|
|
46
|
+
},
|
|
47
|
+
required: ['start', 'end', 'reason'],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
required: ['removals'],
|
|
52
|
+
};
|
|
53
|
+
// ── Agent ────────────────────────────────────────────────────────────────────
|
|
54
|
+
class SilenceRemovalAgent extends BaseAgent {
|
|
55
|
+
removals = [];
|
|
56
|
+
constructor() {
|
|
57
|
+
super('SilenceRemovalAgent', SYSTEM_PROMPT);
|
|
58
|
+
}
|
|
59
|
+
getTools() {
|
|
60
|
+
return [
|
|
61
|
+
{
|
|
62
|
+
name: 'decide_removals',
|
|
63
|
+
description: 'Submit the list of silence regions to remove. Call this once with all removal decisions.',
|
|
64
|
+
parameters: DECIDE_REMOVALS_SCHEMA,
|
|
65
|
+
handler: async (args) => {
|
|
66
|
+
return this.handleToolCall('decide_removals', args);
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
}
|
|
71
|
+
async handleToolCall(toolName, args) {
|
|
72
|
+
if (toolName === 'decide_removals') {
|
|
73
|
+
this.removals = args.removals;
|
|
74
|
+
logger.info(`[SilenceRemovalAgent] Decided to remove ${this.removals.length} silence regions`);
|
|
75
|
+
return { success: true, count: this.removals.length };
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
78
|
+
}
|
|
79
|
+
getRemovals() {
|
|
80
|
+
return this.removals;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// ── FFmpeg helpers ───────────────────────────────────────────────────────────
|
|
84
|
+
function getVideoDuration(videoPath) {
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
ffmpeg.ffprobe(videoPath, (err, metadata) => {
|
|
87
|
+
if (err)
|
|
88
|
+
return reject(new Error(`ffprobe failed: ${err.message}`));
|
|
89
|
+
resolve(metadata.format.duration ?? 0);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// ── Public API ───────────────────────────────────────────────────────────────
|
|
94
|
+
/**
|
|
95
|
+
* Detect silence, use the agent to decide context-aware removals, and produce
|
|
96
|
+
* an edited video with dead silence removed.
|
|
97
|
+
*
|
|
98
|
+
* Returns the path to the edited video, or the original path if no edits were needed.
|
|
99
|
+
*/
|
|
100
|
+
export async function removeDeadSilence(video, transcript) {
|
|
101
|
+
const noEdit = { editedPath: video.repoPath, removals: [], keepSegments: [], wasEdited: false };
|
|
102
|
+
// 1. Detect silence regions (FFmpeg already filters to >= 0.5s via d=0.5)
|
|
103
|
+
const silenceRegions = await detectSilence(video.repoPath, 0.5);
|
|
104
|
+
if (silenceRegions.length === 0) {
|
|
105
|
+
logger.info('[SilenceRemoval] No silence regions detected — skipping');
|
|
106
|
+
return noEdit;
|
|
107
|
+
}
|
|
108
|
+
const totalSilence = silenceRegions.reduce((sum, r) => sum + r.duration, 0);
|
|
109
|
+
logger.info(`[SilenceRemoval] ${silenceRegions.length} silence regions detected (${totalSilence.toFixed(1)}s total silence)`);
|
|
110
|
+
// Only send silence regions >= 2s to the agent; short pauses are natural speech rhythm
|
|
111
|
+
let regionsForAgent = silenceRegions.filter(r => r.duration >= 2);
|
|
112
|
+
if (regionsForAgent.length === 0) {
|
|
113
|
+
logger.info('[SilenceRemoval] No silence regions >= 2s — skipping');
|
|
114
|
+
return noEdit;
|
|
115
|
+
}
|
|
116
|
+
// Cap at 30 longest regions to fit in context window
|
|
117
|
+
if (regionsForAgent.length > 30) {
|
|
118
|
+
regionsForAgent = [...regionsForAgent].sort((a, b) => b.duration - a.duration).slice(0, 30);
|
|
119
|
+
regionsForAgent.sort((a, b) => a.start - b.start); // restore chronological order
|
|
120
|
+
logger.info(`[SilenceRemoval] Capped to top 30 longest regions for agent analysis`);
|
|
121
|
+
}
|
|
122
|
+
// 2. Run the agent to decide which silences to remove
|
|
123
|
+
const agent = new SilenceRemovalAgent();
|
|
124
|
+
const transcriptLines = transcript.segments.map((seg) => `[${seg.start.toFixed(2)}s – ${seg.end.toFixed(2)}s] ${seg.text}`);
|
|
125
|
+
const silenceLines = regionsForAgent.map((r, i) => `${i + 1}. ${r.start.toFixed(2)}s – ${r.end.toFixed(2)}s (${r.duration.toFixed(2)}s)`);
|
|
126
|
+
const prompt = [
|
|
127
|
+
`Video: ${video.filename} (${transcript.duration.toFixed(1)}s total)\n`,
|
|
128
|
+
'--- TRANSCRIPT ---\n',
|
|
129
|
+
transcriptLines.join('\n'),
|
|
130
|
+
'\n--- END TRANSCRIPT ---\n',
|
|
131
|
+
'--- SILENCE REGIONS ---\n',
|
|
132
|
+
silenceLines.join('\n'),
|
|
133
|
+
'\n--- END SILENCE REGIONS ---\n',
|
|
134
|
+
'Analyze the context around each silence region and decide which to remove.',
|
|
135
|
+
].join('\n');
|
|
136
|
+
let removals;
|
|
137
|
+
try {
|
|
138
|
+
await agent.run(prompt);
|
|
139
|
+
removals = agent.getRemovals();
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
await agent.destroy();
|
|
143
|
+
}
|
|
144
|
+
if (removals.length === 0) {
|
|
145
|
+
logger.info('[SilenceRemoval] Agent decided to keep all silences — skipping edit');
|
|
146
|
+
return noEdit;
|
|
147
|
+
}
|
|
148
|
+
// Safety: cap removals at 20% of video duration
|
|
149
|
+
const maxRemoval = transcript.duration * 0.20;
|
|
150
|
+
let totalRemoval = 0;
|
|
151
|
+
const cappedRemovals = [];
|
|
152
|
+
const byDuration = [...removals].sort((a, b) => (b.end - b.start) - (a.end - a.start));
|
|
153
|
+
for (const r of byDuration) {
|
|
154
|
+
const dur = r.end - r.start;
|
|
155
|
+
if (totalRemoval + dur <= maxRemoval) {
|
|
156
|
+
cappedRemovals.push(r);
|
|
157
|
+
totalRemoval += dur;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (cappedRemovals.length < removals.length) {
|
|
161
|
+
logger.warn(`[SilenceRemoval] Capped from ${removals.length} to ${cappedRemovals.length} regions (${totalRemoval.toFixed(1)}s) to stay under 20% threshold`);
|
|
162
|
+
}
|
|
163
|
+
removals = cappedRemovals;
|
|
164
|
+
if (removals.length === 0) {
|
|
165
|
+
logger.info('[SilenceRemoval] All removals exceeded 20% cap — skipping edit');
|
|
166
|
+
return noEdit;
|
|
167
|
+
}
|
|
168
|
+
// 3. Build list of segments to KEEP (inverse of removal regions)
|
|
169
|
+
const videoDuration = await getVideoDuration(video.repoPath);
|
|
170
|
+
const sortedRemovals = [...removals].sort((a, b) => a.start - b.start);
|
|
171
|
+
const keepSegments = [];
|
|
172
|
+
let cursor = 0;
|
|
173
|
+
for (const removal of sortedRemovals) {
|
|
174
|
+
if (removal.start > cursor) {
|
|
175
|
+
keepSegments.push({ start: cursor, end: removal.start });
|
|
176
|
+
}
|
|
177
|
+
cursor = Math.max(cursor, removal.end);
|
|
178
|
+
}
|
|
179
|
+
if (cursor < videoDuration) {
|
|
180
|
+
keepSegments.push({ start: cursor, end: videoDuration });
|
|
181
|
+
}
|
|
182
|
+
if (keepSegments.length === 0) {
|
|
183
|
+
logger.warn('[SilenceRemoval] No segments to keep — returning original');
|
|
184
|
+
return noEdit;
|
|
185
|
+
}
|
|
186
|
+
// 4. Single-pass re-encode with trim+setpts+concat for frame-accurate cuts
|
|
187
|
+
const editedPath = path.join(video.videoDir, `${video.slug}-edited.mp4`);
|
|
188
|
+
await singlePassEdit(video.repoPath, keepSegments, editedPath);
|
|
189
|
+
// Compute effective removals (merged, non-overlapping) from keep-segments
|
|
190
|
+
const effectiveRemovals = [];
|
|
191
|
+
let prevEnd = 0;
|
|
192
|
+
for (const seg of keepSegments) {
|
|
193
|
+
if (seg.start > prevEnd) {
|
|
194
|
+
effectiveRemovals.push({ start: prevEnd, end: seg.start });
|
|
195
|
+
}
|
|
196
|
+
prevEnd = seg.end;
|
|
197
|
+
}
|
|
198
|
+
// Don't add trailing silence as a "removal" — it's just the end of the video
|
|
199
|
+
const actualRemoved = effectiveRemovals.reduce((sum, r) => sum + (r.end - r.start), 0);
|
|
200
|
+
logger.info(`[SilenceRemoval] Removed ${effectiveRemovals.length} silence regions (${actualRemoved.toFixed(1)}s). Output: ${editedPath}`);
|
|
201
|
+
return {
|
|
202
|
+
editedPath,
|
|
203
|
+
removals: effectiveRemovals,
|
|
204
|
+
keepSegments,
|
|
205
|
+
wasEdited: true,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=SilenceRemovalAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SilenceRemovalAgent.js","sourceRoot":"","sources":["../../src/agents/SilenceRemovalAgent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ShortClip, SocialPost, Transcript, VideoFile, VideoSummary } from '../types';
|
|
2
|
+
export declare function generateShortPosts(video: VideoFile, short: ShortClip, transcript: Transcript): Promise<SocialPost[]>;
|
|
3
|
+
export declare function generateSocialPosts(video: VideoFile, transcript: Transcript, summary: VideoSummary, outputDir?: string): Promise<SocialPost[]>;
|
|
4
|
+
//# sourceMappingURL=SocialMediaAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SocialMediaAgent.d.ts","sourceRoot":"","sources":["../../src/agents/SocialMediaAgent.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,YAAY,EACb,MAAM,UAAU,CAAA;AAwMjB,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,UAAU,EAAE,CAAC,CAyDvB;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,YAAY,EACrB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,EAAE,CAAC,CAsDvB"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { BaseAgent } from './BaseAgent';
|
|
4
|
+
import logger from '../config/logger';
|
|
5
|
+
import { searchWeb } from '../tools/search/exaClient';
|
|
6
|
+
import { Platform, } from '../types';
|
|
7
|
+
// ── System prompt ───────────────────────────────────────────────────────────
|
|
8
|
+
const SYSTEM_PROMPT = `You are a viral social-media content strategist.
|
|
9
|
+
Given a video transcript and summary you MUST generate one post for each of the 5 platforms listed below.
|
|
10
|
+
Each post must match the platform's tone, format, and constraints exactly.
|
|
11
|
+
|
|
12
|
+
Platform guidelines:
|
|
13
|
+
1. **TikTok** – Casual, hook-driven, trending hashtags, 150 chars max, emoji-heavy.
|
|
14
|
+
2. **YouTube** – Descriptive, SEO-optimized title + description, relevant tags.
|
|
15
|
+
3. **Instagram** – Visual storytelling, emoji-rich, 30 hashtags max, engaging caption.
|
|
16
|
+
4. **LinkedIn** – Professional, thought-leadership, industry insights, 1-3 hashtags.
|
|
17
|
+
5. **X (Twitter)** – Concise, punchy, 280 chars max, 2-5 hashtags, thread-ready.
|
|
18
|
+
|
|
19
|
+
IMPORTANT – Content format:
|
|
20
|
+
The "content" field you provide must be the FINAL, ready-to-post text that can be directly copied and pasted onto the platform. Do NOT use markdown headers, bullet points, or any formatting inside the content. Include hashtags inline at the end of the post text where appropriate. The content is saved as-is for direct posting.
|
|
21
|
+
|
|
22
|
+
Workflow:
|
|
23
|
+
1. First call the "search_links" tool with the key topics to find relevant URLs.
|
|
24
|
+
2. Then call the "create_posts" tool with a JSON object that has a "posts" array.
|
|
25
|
+
Each element must have: platform, content, hashtags (array), links (array), characterCount.
|
|
26
|
+
|
|
27
|
+
Include relevant links in posts when search results provide them.
|
|
28
|
+
Always call "create_posts" exactly once with all 5 platform posts.`;
|
|
29
|
+
// ── Agent ────────────────────────────────────────────────────────────────────
|
|
30
|
+
class SocialMediaAgent extends BaseAgent {
|
|
31
|
+
collectedPosts = [];
|
|
32
|
+
constructor() {
|
|
33
|
+
super('SocialMediaAgent', SYSTEM_PROMPT);
|
|
34
|
+
}
|
|
35
|
+
getTools() {
|
|
36
|
+
return [
|
|
37
|
+
{
|
|
38
|
+
name: 'search_links',
|
|
39
|
+
description: 'Search for relevant URLs based on topics discussed in the video.',
|
|
40
|
+
parameters: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
properties: {
|
|
43
|
+
topics: {
|
|
44
|
+
type: 'array',
|
|
45
|
+
items: { type: 'string' },
|
|
46
|
+
description: 'List of topics to search for',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ['topics'],
|
|
50
|
+
},
|
|
51
|
+
handler: async (args) => {
|
|
52
|
+
const { topics } = args;
|
|
53
|
+
logger.info(`[SocialMediaAgent] search_links called with topics: ${topics.join(', ')}`);
|
|
54
|
+
const allResults = {};
|
|
55
|
+
for (const topic of topics) {
|
|
56
|
+
allResults[topic] = await searchWeb(topic, 3);
|
|
57
|
+
}
|
|
58
|
+
return JSON.stringify({ results: allResults });
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'create_posts',
|
|
63
|
+
description: 'Submit the generated social media posts for all 5 platforms.',
|
|
64
|
+
parameters: {
|
|
65
|
+
type: 'object',
|
|
66
|
+
properties: {
|
|
67
|
+
posts: {
|
|
68
|
+
type: 'array',
|
|
69
|
+
items: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
platform: { type: 'string' },
|
|
73
|
+
content: { type: 'string' },
|
|
74
|
+
hashtags: { type: 'array', items: { type: 'string' } },
|
|
75
|
+
links: { type: 'array', items: { type: 'string' } },
|
|
76
|
+
characterCount: { type: 'number' },
|
|
77
|
+
},
|
|
78
|
+
required: ['platform', 'content', 'hashtags', 'links', 'characterCount'],
|
|
79
|
+
},
|
|
80
|
+
description: 'Array of posts, one per platform',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
required: ['posts'],
|
|
84
|
+
},
|
|
85
|
+
handler: async (args) => {
|
|
86
|
+
const { posts } = args;
|
|
87
|
+
this.collectedPosts = posts;
|
|
88
|
+
logger.info(`[SocialMediaAgent] create_posts received ${posts.length} posts`);
|
|
89
|
+
return JSON.stringify({ success: true, count: posts.length });
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
async handleToolCall(toolName, args) {
|
|
95
|
+
// Tool dispatch is handled inline via tool handlers above.
|
|
96
|
+
// This satisfies the abstract contract from BaseAgent.
|
|
97
|
+
logger.warn(`[SocialMediaAgent] Unexpected handleToolCall for "${toolName}"`);
|
|
98
|
+
return { error: `Unknown tool: ${toolName}` };
|
|
99
|
+
}
|
|
100
|
+
getCollectedPosts() {
|
|
101
|
+
return this.collectedPosts;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// ── Helper: map raw platform string → Platform enum ─────────────────────────
|
|
105
|
+
function toPlatformEnum(raw) {
|
|
106
|
+
const normalised = raw.toLowerCase().trim();
|
|
107
|
+
switch (normalised) {
|
|
108
|
+
case 'tiktok':
|
|
109
|
+
return Platform.TikTok;
|
|
110
|
+
case 'youtube':
|
|
111
|
+
return Platform.YouTube;
|
|
112
|
+
case 'instagram':
|
|
113
|
+
return Platform.Instagram;
|
|
114
|
+
case 'linkedin':
|
|
115
|
+
return Platform.LinkedIn;
|
|
116
|
+
case 'x':
|
|
117
|
+
case 'twitter':
|
|
118
|
+
return Platform.X;
|
|
119
|
+
default:
|
|
120
|
+
return normalised;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function renderPostFile(post, opts) {
|
|
124
|
+
const now = new Date().toISOString();
|
|
125
|
+
const platform = toPlatformEnum(post.platform);
|
|
126
|
+
const lines = ['---'];
|
|
127
|
+
lines.push(`platform: ${platform}`);
|
|
128
|
+
lines.push(`status: draft`);
|
|
129
|
+
lines.push(`scheduledDate: null`);
|
|
130
|
+
if (post.hashtags.length > 0) {
|
|
131
|
+
lines.push('hashtags:');
|
|
132
|
+
for (const tag of post.hashtags) {
|
|
133
|
+
lines.push(` - "${tag}"`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
lines.push('hashtags: []');
|
|
138
|
+
}
|
|
139
|
+
if (post.links.length > 0) {
|
|
140
|
+
lines.push('links:');
|
|
141
|
+
for (const link of post.links) {
|
|
142
|
+
lines.push(` - url: "${link}"`);
|
|
143
|
+
lines.push(` title: null`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
lines.push('links: []');
|
|
148
|
+
}
|
|
149
|
+
lines.push(`characterCount: ${post.characterCount}`);
|
|
150
|
+
lines.push(`videoSlug: "${opts.videoSlug}"`);
|
|
151
|
+
lines.push(`shortSlug: ${opts.shortSlug ? `"${opts.shortSlug}"` : 'null'}`);
|
|
152
|
+
lines.push(`createdAt: "${now}"`);
|
|
153
|
+
lines.push('---');
|
|
154
|
+
lines.push('');
|
|
155
|
+
lines.push(post.content);
|
|
156
|
+
lines.push('');
|
|
157
|
+
return lines.join('\n');
|
|
158
|
+
}
|
|
159
|
+
// ── Public API ──────────────────────────────────────────────────────────────
|
|
160
|
+
export async function generateShortPosts(video, short, transcript) {
|
|
161
|
+
const agent = new SocialMediaAgent();
|
|
162
|
+
try {
|
|
163
|
+
// Extract transcript segments that overlap with the short's time ranges
|
|
164
|
+
const relevantText = transcript.segments
|
|
165
|
+
.filter((seg) => short.segments.some((ss) => seg.start < ss.end && seg.end > ss.start))
|
|
166
|
+
.map((seg) => seg.text)
|
|
167
|
+
.join(' ');
|
|
168
|
+
const userMessage = [
|
|
169
|
+
'## Short Clip Metadata',
|
|
170
|
+
`- **Title:** ${short.title}`,
|
|
171
|
+
`- **Description:** ${short.description}`,
|
|
172
|
+
`- **Duration:** ${short.totalDuration.toFixed(1)}s`,
|
|
173
|
+
`- **Tags:** ${short.tags.join(', ')}`,
|
|
174
|
+
'',
|
|
175
|
+
'## Relevant Transcript',
|
|
176
|
+
relevantText.slice(0, 3000),
|
|
177
|
+
].join('\n');
|
|
178
|
+
await agent.run(userMessage);
|
|
179
|
+
const collectedPosts = agent.getCollectedPosts();
|
|
180
|
+
// Save posts to recordings/{slug}/shorts/{short-slug}/posts/
|
|
181
|
+
const shortsDir = path.join(path.dirname(video.repoPath), 'shorts');
|
|
182
|
+
const postsDir = path.join(shortsDir, short.slug, 'posts');
|
|
183
|
+
fs.mkdirSync(postsDir, { recursive: true });
|
|
184
|
+
const socialPosts = collectedPosts.map((p) => {
|
|
185
|
+
const platform = toPlatformEnum(p.platform);
|
|
186
|
+
const outputPath = path.join(postsDir, `${platform}.md`);
|
|
187
|
+
fs.writeFileSync(outputPath, renderPostFile(p, { videoSlug: video.slug, shortSlug: short.slug }), 'utf-8');
|
|
188
|
+
logger.info(`[SocialMediaAgent] Wrote short post ${outputPath}`);
|
|
189
|
+
return {
|
|
190
|
+
platform,
|
|
191
|
+
content: p.content,
|
|
192
|
+
hashtags: p.hashtags,
|
|
193
|
+
links: p.links,
|
|
194
|
+
characterCount: p.characterCount,
|
|
195
|
+
outputPath,
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
return socialPosts;
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
await agent.destroy();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
export async function generateSocialPosts(video, transcript, summary, outputDir) {
|
|
205
|
+
const agent = new SocialMediaAgent();
|
|
206
|
+
try {
|
|
207
|
+
// Build the user prompt with transcript summary and metadata
|
|
208
|
+
const userMessage = [
|
|
209
|
+
'## Video Metadata',
|
|
210
|
+
`- **Title:** ${summary.title}`,
|
|
211
|
+
`- **Slug:** ${video.slug}`,
|
|
212
|
+
`- **Duration:** ${video.duration}s`,
|
|
213
|
+
'',
|
|
214
|
+
'## Summary',
|
|
215
|
+
summary.overview,
|
|
216
|
+
'',
|
|
217
|
+
'## Key Topics',
|
|
218
|
+
summary.keyTopics.map((t) => `- ${t}`).join('\n'),
|
|
219
|
+
'',
|
|
220
|
+
'## Transcript (first 3000 chars)',
|
|
221
|
+
transcript.text.slice(0, 3000),
|
|
222
|
+
].join('\n');
|
|
223
|
+
await agent.run(userMessage);
|
|
224
|
+
const collectedPosts = agent.getCollectedPosts();
|
|
225
|
+
// Ensure the output directory exists
|
|
226
|
+
const outDir = outputDir ?? path.join(video.videoDir, 'social-posts');
|
|
227
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
228
|
+
const socialPosts = collectedPosts.map((p) => {
|
|
229
|
+
const platform = toPlatformEnum(p.platform);
|
|
230
|
+
const outputPath = path.join(outDir, `${platform}.md`);
|
|
231
|
+
fs.writeFileSync(outputPath, renderPostFile(p, { videoSlug: video.slug }), 'utf-8');
|
|
232
|
+
logger.info(`[SocialMediaAgent] Wrote ${outputPath}`);
|
|
233
|
+
return {
|
|
234
|
+
platform,
|
|
235
|
+
content: p.content,
|
|
236
|
+
hashtags: p.hashtags,
|
|
237
|
+
links: p.links,
|
|
238
|
+
characterCount: p.characterCount,
|
|
239
|
+
outputPath,
|
|
240
|
+
};
|
|
241
|
+
});
|
|
242
|
+
return socialPosts;
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
await agent.destroy();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=SocialMediaAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SocialMediaAgent.js","sourceRoot":"","sources":["../../src/agents/SocialMediaAgent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,MAAM,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EACL,QAAQ,GAMT,MAAM,UAAU,CAAA;AAoBjB,+EAA+E;AAE/E,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;mEAoB6C,CAAA;AAEnE,gFAAgF;AAEhF,MAAM,gBAAiB,SAAQ,SAAS;IAC9B,cAAc,GAAmB,EAAE,CAAA;IAE3C;QACE,KAAK,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAA;IAC1C,CAAC;IAES,QAAQ;QAChB,OAAO;YACL;gBACE,IAAI,EAAE,cAAc;gBACpB,WAAW,EACT,kEAAkE;gBACpE,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,MAAM,EAAE;4BACN,IAAI,EAAE,OAAO;4BACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;4BACzB,WAAW,EAAE,8BAA8B;yBAC5C;qBACF;oBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;iBACrB;gBACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;oBAC/B,MAAM,EAAE,MAAM,EAAE,GAAG,IAAuB,CAAA;oBAC1C,MAAM,CAAC,IAAI,CAAC,uDAAuD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;oBACvF,MAAM,UAAU,GAAsE,EAAE,CAAA;oBACxF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;wBAC3B,UAAU,CAAC,KAAK,CAAC,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;oBAC/C,CAAC;oBACD,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAA;gBAChD,CAAC;aACF;YACD;gBACE,IAAI,EAAE,cAAc;gBACpB,WAAW,EACT,8DAA8D;gBAChE,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,KAAK,EAAE;4BACL,IAAI,EAAE,OAAO;4BACb,KAAK,EAAE;gCACL,IAAI,EAAE,QAAQ;gCACd,UAAU,EAAE;oCACV,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oCAC5B,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oCAC3B,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oCACtD,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oCACnD,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;iCACnC;gCACD,QAAQ,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,CAAC;6BACzE;4BACD,WAAW,EAAE,kCAAkC;yBAChD;qBACF;oBACD,QAAQ,EAAE,CAAC,OAAO,CAAC;iBACpB;gBACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;oBAC/B,MAAM,EAAE,KAAK,EAAE,GAAG,IAAuB,CAAA;oBACzC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAA;oBAC3B,MAAM,CAAC,IAAI,CAAC,4CAA4C,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAA;oBAC7E,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;gBAC/D,CAAC;aACF;SACF,CAAA;IACH,CAAC;IAES,KAAK,CAAC,cAAc,CAC5B,QAAgB,EAChB,IAA6B;QAE7B,2DAA2D;QAC3D,uDAAuD;QACvD,MAAM,CAAC,IAAI,CAAC,qDAAqD,QAAQ,GAAG,CAAC,CAAA;QAC7E,OAAO,EAAE,KAAK,EAAE,iBAAiB,QAAQ,EAAE,EAAE,CAAA;IAC/C,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,cAAc,CAAA;IAC5B,CAAC;CACF;AAED,+EAA+E;AAE/E,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;IAC3C,QAAQ,UAAU,EAAE,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC,MAAM,CAAA;QACxB,KAAK,SAAS;YACZ,OAAO,QAAQ,CAAC,OAAO,CAAA;QACzB,KAAK,WAAW;YACd,OAAO,QAAQ,CAAC,SAAS,CAAA;QAC3B,KAAK,UAAU;YACb,OAAO,QAAQ,CAAC,QAAQ,CAAA;QAC1B,KAAK,GAAG,CAAC;QACT,KAAK,SAAS;YACZ,OAAO,QAAQ,CAAC,CAAC,CAAA;QACnB;YACE,OAAO,UAAsB,CAAA;IACjC,CAAC;AACH,CAAC;AASD,SAAS,cAAc,CAAC,IAAkB,EAAE,IAAoB;IAC9D,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC9C,MAAM,KAAK,GAAa,CAAC,KAAK,CAAC,CAAA;IAE/B,KAAK,CAAC,IAAI,CAAC,aAAa,QAAQ,EAAE,CAAC,CAAA;IACnC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAC3B,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;IAEjC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACvB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAA;QAC5B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC5B,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACpB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,GAAG,CAAC,CAAA;YAChC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,cAAc,EAAE,CAAC,CAAA;IACpD,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,SAAS,GAAG,CAAC,CAAA;IAC5C,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;IAC3E,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC,CAAA;IACjC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,+EAA+E;AAE/E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAgB,EAChB,KAAgB,EAChB,UAAsB;IAEtB,MAAM,KAAK,GAAG,IAAI,gBAAgB,EAAE,CAAA;IAEpC,IAAI,CAAC;QACH,wEAAwE;QACxE,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ;aACrC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CACd,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,CACtE;aACA,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;aACtB,IAAI,CAAC,GAAG,CAAC,CAAA;QAEZ,MAAM,WAAW,GAAG;YAClB,wBAAwB;YACxB,gBAAgB,KAAK,CAAC,KAAK,EAAE;YAC7B,sBAAsB,KAAK,CAAC,WAAW,EAAE;YACzC,mBAAmB,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;YACpD,eAAe,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACtC,EAAE;YACF,wBAAwB;YACxB,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;SAC5B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEZ,MAAM,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAE5B,MAAM,cAAc,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEhD,6DAA6D;QAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAA;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAC1D,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAE3C,MAAM,WAAW,GAAiB,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACzD,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;YAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAA;YAExD,EAAE,CAAC,aAAa,CACd,UAAU,EACV,cAAc,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EACnE,OAAO,CACR,CAAA;YACD,MAAM,CAAC,IAAI,CAAC,uCAAuC,UAAU,EAAE,CAAC,CAAA;YAEhE,OAAO;gBACL,QAAQ;gBACR,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,cAAc,EAAE,CAAC,CAAC,cAAc;gBAChC,UAAU;aACX,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,OAAO,WAAW,CAAA;IACpB,CAAC;YAAS,CAAC;QACT,MAAM,KAAK,CAAC,OAAO,EAAE,CAAA;IACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAgB,EAChB,UAAsB,EACtB,OAAqB,EACrB,SAAkB;IAElB,MAAM,KAAK,GAAG,IAAI,gBAAgB,EAAE,CAAA;IAEpC,IAAI,CAAC;QACH,6DAA6D;QAC7D,MAAM,WAAW,GAAG;YAClB,mBAAmB;YACnB,gBAAgB,OAAO,CAAC,KAAK,EAAE;YAC/B,eAAe,KAAK,CAAC,IAAI,EAAE;YAC3B,mBAAmB,KAAK,CAAC,QAAQ,GAAG;YACpC,EAAE;YACF,YAAY;YACZ,OAAO,CAAC,QAAQ;YAChB,EAAE;YACF,eAAe;YACf,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YACjD,EAAE;YACF,kCAAkC;YAClC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;SAC/B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEZ,MAAM,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAE5B,MAAM,cAAc,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEhD,qCAAqC;QACrC,MAAM,MAAM,GAAG,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;QACrE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAEzC,MAAM,WAAW,GAAiB,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACzD,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;YAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAA;YAEtD,EAAE,CAAC,aAAa,CACd,UAAU,EACV,cAAc,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EAC5C,OAAO,CACR,CAAA;YACD,MAAM,CAAC,IAAI,CAAC,4BAA4B,UAAU,EAAE,CAAC,CAAA;YAErD,OAAO;gBACL,QAAQ;gBACR,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,cAAc,EAAE,CAAC,CAAC,cAAc;gBAChC,UAAU;aACX,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,OAAO,WAAW,CAAA;IACpB,CAAC;YAAS,CAAC;QACT,MAAM,KAAK,CAAC,OAAO,EAAE,CAAA;IACvB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { VideoFile, Transcript, VideoSummary, ShortClip, Chapter } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Generate a beautiful Markdown summary for a video recording.
|
|
4
|
+
*
|
|
5
|
+
* 1. Creates a SummaryAgent with `capture_frame` and `write_summary` tools
|
|
6
|
+
* 2. Builds a prompt containing the full transcript with timestamps
|
|
7
|
+
* 3. Lets the agent analyse the transcript, capture key frames, and write Markdown
|
|
8
|
+
* 4. Returns a {@link VideoSummary} with metadata and snapshot paths
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateSummary(video: VideoFile, transcript: Transcript, shorts?: ShortClip[], chapters?: Chapter[]): Promise<VideoSummary>;
|
|
11
|
+
//# sourceMappingURL=SummaryAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SummaryAgent.d.ts","sourceRoot":"","sources":["../../src/agents/SummaryAgent.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAiB,SAAS,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AA+TtG;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,UAAU,EACtB,MAAM,CAAC,EAAE,SAAS,EAAE,EACpB,QAAQ,CAAC,EAAE,OAAO,EAAE,GACnB,OAAO,CAAC,YAAY,CAAC,CA+DvB"}
|