@brickgale/caption-sync 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/LICENSE +21 -0
- package/README.md +261 -0
- package/dist/components/Video.d.ts +29 -0
- package/dist/components/Video.d.ts.map +1 -0
- package/dist/components/Video.js +243 -0
- package/dist/components/Video.js.map +1 -0
- package/dist/config.d.ts +148 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +141 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/elevenlabs-provider.d.ts +13 -0
- package/dist/providers/elevenlabs-provider.d.ts.map +1 -0
- package/dist/providers/elevenlabs-provider.js +117 -0
- package/dist/providers/elevenlabs-provider.js.map +1 -0
- package/dist/providers/index.d.ts +30 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +47 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai-provider.d.ts +13 -0
- package/dist/providers/openai-provider.d.ts.map +1 -0
- package/dist/providers/openai-provider.js +85 -0
- package/dist/providers/openai-provider.js.map +1 -0
- package/dist/providers/transcription-provider.d.ts +37 -0
- package/dist/providers/transcription-provider.d.ts.map +1 -0
- package/dist/providers/transcription-provider.js +9 -0
- package/dist/providers/transcription-provider.js.map +1 -0
- package/dist/types/index.d.ts +106 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/caption-generator.d.ts +128 -0
- package/dist/utils/caption-generator.d.ts.map +1 -0
- package/dist/utils/caption-generator.js +400 -0
- package/dist/utils/caption-generator.js.map +1 -0
- package/dist/utils/transcription.d.ts +96 -0
- package/dist/utils/transcription.d.ts.map +1 -0
- package/dist/utils/transcription.js +280 -0
- package/dist/utils/transcription.js.map +1 -0
- package/dist/utils/video-renderer.d.ts +58 -0
- package/dist/utils/video-renderer.d.ts.map +1 -0
- package/dist/utils/video-renderer.js +153 -0
- package/dist/utils/video-renderer.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenAI Whisper Transcription Provider
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.OpenAIProvider = void 0;
|
|
43
|
+
const openai_1 = __importDefault(require("openai"));
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
class OpenAIProvider {
|
|
46
|
+
constructor(apiKey, language = 'en', model = 'whisper-1') {
|
|
47
|
+
this.name = 'OpenAI Whisper';
|
|
48
|
+
this.client = new openai_1.default({ apiKey });
|
|
49
|
+
this.language = language;
|
|
50
|
+
this.model = model;
|
|
51
|
+
}
|
|
52
|
+
async transcribeWithTimestamps(audioPath, options) {
|
|
53
|
+
if (!fs.existsSync(audioPath)) {
|
|
54
|
+
throw new Error(`Audio file not found: ${audioPath}`);
|
|
55
|
+
}
|
|
56
|
+
const language = options?.language || this.language;
|
|
57
|
+
const model = options?.model || this.model;
|
|
58
|
+
try {
|
|
59
|
+
console.log(`🎤 Transcribing with ${this.name}...`);
|
|
60
|
+
const transcription = await this.client.audio.transcriptions.create({
|
|
61
|
+
file: fs.createReadStream(audioPath),
|
|
62
|
+
model,
|
|
63
|
+
language,
|
|
64
|
+
response_format: 'verbose_json',
|
|
65
|
+
timestamp_granularities: ['word'],
|
|
66
|
+
});
|
|
67
|
+
console.log(`✅ ${this.name} transcription complete`);
|
|
68
|
+
// Extract word-level timestamps
|
|
69
|
+
const result = transcription;
|
|
70
|
+
if (result.words && Array.isArray(result.words)) {
|
|
71
|
+
return result.words.map((w) => ({
|
|
72
|
+
word: w.word,
|
|
73
|
+
start: w.start,
|
|
74
|
+
end: w.end,
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
throw new Error('No word-level timestamps in response');
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
throw new Error(`${this.name} transcription failed: ${error.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.OpenAIProvider = OpenAIProvider;
|
|
85
|
+
//# sourceMappingURL=openai-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-provider.js","sourceRoot":"","sources":["../../src/lib/providers/openai-provider.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,oDAA4B;AAC5B,uCAAyB;AAMzB,MAAa,cAAc;IAMzB,YACE,MAAc,EACd,WAAmB,IAAI,EACvB,QAAgB,WAAW;QARpB,SAAI,GAAG,gBAAgB,CAAC;QAU/B,IAAI,CAAC,MAAM,GAAG,IAAI,gBAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,wBAAwB,CAC5B,SAAiB,EACjB,OAA6B;QAE7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,yBAAyB,SAAS,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC;QACpD,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;QAE3C,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;YAEpD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC;gBAClE,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC;gBACpC,KAAK;gBACL,QAAQ;gBACR,eAAe,EAAE,cAAc;gBAC/B,uBAAuB,EAAE,CAAC,MAAM,CAAC;aAClC,CAAC,CAAC;YAEH,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,IAAI,yBAAyB,CAAC,CAAC;YAErD,gCAAgC;YAChC,MAAM,MAAM,GAAG,aAAoB,CAAC;YACpC,IAAI,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChD,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;oBACnC,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,GAAG,EAAE,CAAC,CAAC,GAAG;iBACX,CAAC,CAAC,CAAC;YACN,CAAC;YAED,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,0BAA0B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;CACF;AAvDD,wCAuDC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy Pattern for Transcription Providers
|
|
3
|
+
*
|
|
4
|
+
* This allows easy switching between different speech-to-text services
|
|
5
|
+
* like OpenAI Whisper, ElevenLabs, etc.
|
|
6
|
+
*/
|
|
7
|
+
export interface WordTimestamp {
|
|
8
|
+
word: string;
|
|
9
|
+
start: number;
|
|
10
|
+
end: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Base interface for all transcription providers
|
|
14
|
+
*/
|
|
15
|
+
export interface TranscriptionProvider {
|
|
16
|
+
/**
|
|
17
|
+
* Provider name for logging/debugging
|
|
18
|
+
*/
|
|
19
|
+
readonly name: string;
|
|
20
|
+
/**
|
|
21
|
+
* Transcribe audio with word-level timestamps
|
|
22
|
+
* @param audioPath - Path to audio file
|
|
23
|
+
* @param options - Provider-specific options
|
|
24
|
+
* @returns Array of words with timestamps
|
|
25
|
+
*/
|
|
26
|
+
transcribeWithTimestamps(audioPath: string, options?: Record<string, any>): Promise<WordTimestamp[]>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for transcription providers
|
|
30
|
+
*/
|
|
31
|
+
export interface TranscriptionProviderConfig {
|
|
32
|
+
provider: 'openai' | 'elevenlabs';
|
|
33
|
+
apiKey: string;
|
|
34
|
+
language?: string;
|
|
35
|
+
model?: string;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=transcription-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcription-provider.d.ts","sourceRoot":"","sources":["../../src/lib/providers/transcription-provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,wBAAwB,CACtB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC5B,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Strategy Pattern for Transcription Providers
|
|
4
|
+
*
|
|
5
|
+
* This allows easy switching between different speech-to-text services
|
|
6
|
+
* like OpenAI Whisper, ElevenLabs, etc.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
//# sourceMappingURL=transcription-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcription-provider.js","sourceRoot":"","sources":["../../src/lib/providers/transcription-provider.ts"],"names":[],"mappings":";AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared type definitions for the caption-sync library
|
|
3
|
+
*/
|
|
4
|
+
import type { CaptionPlacement, CaptionAnimation } from '../config';
|
|
5
|
+
/**
|
|
6
|
+
* Word with timestamp information
|
|
7
|
+
*/
|
|
8
|
+
export interface WordTimestamp {
|
|
9
|
+
word: string;
|
|
10
|
+
start: number;
|
|
11
|
+
end: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Caption with timing information
|
|
15
|
+
*/
|
|
16
|
+
export interface Caption {
|
|
17
|
+
start: number;
|
|
18
|
+
end: number;
|
|
19
|
+
text: string;
|
|
20
|
+
words?: WordTimestamp[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Props for the Video component
|
|
24
|
+
*/
|
|
25
|
+
export interface VideoProps {
|
|
26
|
+
audioPath: string;
|
|
27
|
+
captions: Caption[];
|
|
28
|
+
placement?: CaptionPlacement;
|
|
29
|
+
backgroundColor?: string | null;
|
|
30
|
+
canvasBackgroundColor?: string;
|
|
31
|
+
textColor?: string;
|
|
32
|
+
fontSize?: number;
|
|
33
|
+
fontFamily?: string;
|
|
34
|
+
googleFontsUrl?: string | null;
|
|
35
|
+
letterSpacing?: string;
|
|
36
|
+
textShadow?: string;
|
|
37
|
+
textStrokeWidth?: string | null;
|
|
38
|
+
textStrokeColor?: string | null;
|
|
39
|
+
animation?: CaptionAnimation;
|
|
40
|
+
paddingBottom?: string;
|
|
41
|
+
paddingHorizontal?: string;
|
|
42
|
+
maxWidth?: string;
|
|
43
|
+
highlightColor?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Options for generating captions
|
|
47
|
+
*/
|
|
48
|
+
export interface GenerateCaptionsOptions {
|
|
49
|
+
scriptPath: string;
|
|
50
|
+
audioPath: string;
|
|
51
|
+
maxCharacters?: number;
|
|
52
|
+
useTranscription?: boolean;
|
|
53
|
+
openaiApiKey?: string;
|
|
54
|
+
/** Transcription provider: 'openai' or 'elevenlabs' (default: 'elevenlabs') */
|
|
55
|
+
transcriptionProvider?: 'openai' | 'elevenlabs';
|
|
56
|
+
/** ElevenLabs API key (required if using elevenlabs provider) */
|
|
57
|
+
elevenLabsApiKey?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Options for transcribing audio to text
|
|
61
|
+
*/
|
|
62
|
+
export interface TranscribeAudioOptions {
|
|
63
|
+
audioPath: string;
|
|
64
|
+
openaiApiKey: string;
|
|
65
|
+
language?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Text comparison result
|
|
69
|
+
*/
|
|
70
|
+
export interface TextComparisonResult {
|
|
71
|
+
original: string;
|
|
72
|
+
transcribed: string;
|
|
73
|
+
sanitizedOriginal: string;
|
|
74
|
+
sanitizedTranscribed: string;
|
|
75
|
+
differences: string[];
|
|
76
|
+
similarity: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Options for rendering video
|
|
80
|
+
*/
|
|
81
|
+
export interface RenderVideoOptions {
|
|
82
|
+
audioPath: string;
|
|
83
|
+
captions: Caption[];
|
|
84
|
+
outputPath: string;
|
|
85
|
+
compositionPath?: string;
|
|
86
|
+
width?: number;
|
|
87
|
+
height?: number;
|
|
88
|
+
fps?: number;
|
|
89
|
+
placement?: CaptionPlacement;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Options for generating video (captions + render)
|
|
93
|
+
*/
|
|
94
|
+
export interface GenerateVideoOptions {
|
|
95
|
+
scriptPath: string;
|
|
96
|
+
audioPath: string;
|
|
97
|
+
outputPath: string;
|
|
98
|
+
width?: number;
|
|
99
|
+
height?: number;
|
|
100
|
+
fps?: number;
|
|
101
|
+
placement?: CaptionPlacement;
|
|
102
|
+
maxCharacters?: number;
|
|
103
|
+
useTranscription?: boolean;
|
|
104
|
+
openaiApiKey?: string;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/types/index.ts"],"names":[],"mappings":";AAAA;;GAEG"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { Caption, GenerateCaptionsOptions } from '../types';
|
|
2
|
+
import type { WordTimestamp } from '../providers/transcription-provider';
|
|
3
|
+
/**
|
|
4
|
+
* Get audio duration using ffmpeg
|
|
5
|
+
*
|
|
6
|
+
* @param audioPath - Path to audio file
|
|
7
|
+
* @returns Duration in seconds
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const duration = getAudioDuration('./audio.mp3');
|
|
12
|
+
* console.log(`Audio is ${duration} seconds long`);
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function getAudioDuration(audioPath: string): number;
|
|
16
|
+
/**
|
|
17
|
+
* Split text into phrases based on punctuation and natural breaks
|
|
18
|
+
*
|
|
19
|
+
* @param text - Text to split into phrases
|
|
20
|
+
* @returns Array of phrases
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const phrases = splitIntoPhrases("Hello world. This is a test.");
|
|
25
|
+
* // Returns: ["Hello world", "This is a test"]
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function splitIntoPhrases(text: string): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Count words in a phrase
|
|
31
|
+
*
|
|
32
|
+
* @param phrase - Phrase to count words in
|
|
33
|
+
* @returns Number of words
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const count = countWords("Hello world");
|
|
38
|
+
* // Returns: 2
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function countWords(phrase: string): number;
|
|
42
|
+
/**
|
|
43
|
+
* Split long phrases into smaller chunks based on character limit
|
|
44
|
+
*
|
|
45
|
+
* @param phrase - Phrase to split
|
|
46
|
+
* @param maxCharacters - Maximum characters per chunk
|
|
47
|
+
* @returns Array of smaller phrases
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const chunks = splitByCharacterLimit("This is a very long sentence that needs to be split", 20);
|
|
52
|
+
* // Returns: ["This is a very long", "sentence that needs", "to be split"]
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function splitByCharacterLimit(phrase: string, maxCharacters: number): string[];
|
|
56
|
+
/**
|
|
57
|
+
* Generate captions from word-level timestamps with intelligent splitting
|
|
58
|
+
*
|
|
59
|
+
* Groups words into captions based on:
|
|
60
|
+
* - Character limits (hard constraint)
|
|
61
|
+
* - Natural pauses in speech (preferred break points)
|
|
62
|
+
* - Semantic boundaries (proper nouns, conjunctions)
|
|
63
|
+
* - Minimum words per caption (avoid too-short captions)
|
|
64
|
+
*
|
|
65
|
+
* @param words - Array of words with timestamps
|
|
66
|
+
* @param maxCharacters - Maximum characters per caption
|
|
67
|
+
* @returns Array of captions with accurate timing
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const words = [
|
|
72
|
+
* { word: "Hello", start: 0.0, end: 0.5 },
|
|
73
|
+
* { word: "world", start: 0.6, end: 1.0 }
|
|
74
|
+
* ];
|
|
75
|
+
* const captions = generateCaptionsFromWordTimestamps(words, 50);
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare function generateCaptionsFromWordTimestamps(words: WordTimestamp[], maxCharacters: number): Caption[];
|
|
79
|
+
/**
|
|
80
|
+
* Generate caption timing based on weighted distribution
|
|
81
|
+
*
|
|
82
|
+
* This function reads a script file and audio file, then generates
|
|
83
|
+
* caption timing by distributing the audio duration proportionally
|
|
84
|
+
* based on the word count in each phrase.
|
|
85
|
+
*
|
|
86
|
+
* @param options - Configuration options
|
|
87
|
+
* @param options.scriptPath - Path to script text file
|
|
88
|
+
* @param options.audioPath - Path to audio file
|
|
89
|
+
* @param options.maxCharacters - Maximum characters per caption (default: from config)
|
|
90
|
+
* @param options.useTranscription - Use speech-to-text to verify/correct script (default: false)
|
|
91
|
+
* @param options.openaiApiKey - OpenAI API key for transcription
|
|
92
|
+
* @returns Array of captions with timing
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* import { generateCaptions } from 'caption-sync';
|
|
97
|
+
*
|
|
98
|
+
* const captions = generateCaptions({
|
|
99
|
+
* scriptPath: './script.txt',
|
|
100
|
+
* audioPath: './audio.mp3',
|
|
101
|
+
* maxCharacters: 50
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* console.log(captions);
|
|
105
|
+
* // [{ start: 0, end: 2.5, text: "Hello world." }, ...]
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare function generateCaptions(options: GenerateCaptionsOptions): Promise<Caption[]>;
|
|
109
|
+
/**
|
|
110
|
+
* Generate captions from text content directly (no file I/O)
|
|
111
|
+
*
|
|
112
|
+
* Useful when you already have the script content in memory
|
|
113
|
+
* and don't want to write it to a file first.
|
|
114
|
+
*
|
|
115
|
+
* @param scriptText - The script text content
|
|
116
|
+
* @param audioPath - Path to audio file
|
|
117
|
+
* @returns Array of captions with timing
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* import { generateCaptionsFromText } from 'caption-sync';
|
|
122
|
+
*
|
|
123
|
+
* const script = "Hello world. This is a test.";
|
|
124
|
+
* const captions = generateCaptionsFromText(script, "./audio.mp3");
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export declare function generateCaptionsFromText(scriptText: string, audioPath: string): Caption[];
|
|
128
|
+
//# sourceMappingURL=caption-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caption-generator.d.ts","sourceRoot":"","sources":["../../src/lib/utils/caption-generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAIjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAEzE;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgB1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAWvD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,MAAM,EAAE,CA2BV;AAgDD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,aAAa,EAAE,EACtB,aAAa,EAAE,MAAM,GACpB,OAAO,EAAE,CAmEX;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,OAAO,EAAE,CAAC,CAgGpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,EAAE,CAoCX"}
|