playwright-recast 0.1.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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +282 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +139 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/filter/step-filter.d.ts +7 -0
  8. package/dist/filter/step-filter.d.ts.map +1 -0
  9. package/dist/filter/step-filter.js +23 -0
  10. package/dist/filter/step-filter.js.map +1 -0
  11. package/dist/helpers.d.ts +41 -0
  12. package/dist/helpers.d.ts.map +1 -0
  13. package/dist/helpers.js +73 -0
  14. package/dist/helpers.js.map +1 -0
  15. package/dist/index.d.ts +10 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +8 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/parse/jsonl-parser.d.ts +87 -0
  20. package/dist/parse/jsonl-parser.d.ts.map +1 -0
  21. package/dist/parse/jsonl-parser.js +17 -0
  22. package/dist/parse/jsonl-parser.js.map +1 -0
  23. package/dist/parse/trace-parser.d.ts +6 -0
  24. package/dist/parse/trace-parser.d.ts.map +1 -0
  25. package/dist/parse/trace-parser.js +149 -0
  26. package/dist/parse/trace-parser.js.map +1 -0
  27. package/dist/parse/zip-reader.d.ts +21 -0
  28. package/dist/parse/zip-reader.d.ts.map +1 -0
  29. package/dist/parse/zip-reader.js +45 -0
  30. package/dist/parse/zip-reader.js.map +1 -0
  31. package/dist/pipeline/executor.d.ts +16 -0
  32. package/dist/pipeline/executor.d.ts.map +1 -0
  33. package/dist/pipeline/executor.js +283 -0
  34. package/dist/pipeline/executor.js.map +1 -0
  35. package/dist/pipeline/pipeline.d.ts +79 -0
  36. package/dist/pipeline/pipeline.d.ts.map +1 -0
  37. package/dist/pipeline/pipeline.js +105 -0
  38. package/dist/pipeline/pipeline.js.map +1 -0
  39. package/dist/pipeline/stages.d.ts +49 -0
  40. package/dist/pipeline/stages.d.ts.map +1 -0
  41. package/dist/pipeline/stages.js +2 -0
  42. package/dist/pipeline/stages.js.map +1 -0
  43. package/dist/render/renderer.d.ts +22 -0
  44. package/dist/render/renderer.d.ts.map +1 -0
  45. package/dist/render/renderer.js +174 -0
  46. package/dist/render/renderer.js.map +1 -0
  47. package/dist/speed/classifiers.d.ts +8 -0
  48. package/dist/speed/classifiers.d.ts.map +1 -0
  49. package/dist/speed/classifiers.js +38 -0
  50. package/dist/speed/classifiers.js.map +1 -0
  51. package/dist/speed/speed-processor.d.ts +9 -0
  52. package/dist/speed/speed-processor.d.ts.map +1 -0
  53. package/dist/speed/speed-processor.js +97 -0
  54. package/dist/speed/speed-processor.js.map +1 -0
  55. package/dist/speed/time-remap.d.ts +12 -0
  56. package/dist/speed/time-remap.d.ts.map +1 -0
  57. package/dist/speed/time-remap.js +44 -0
  58. package/dist/speed/time-remap.js.map +1 -0
  59. package/dist/subtitles/srt-parser.d.ts +4 -0
  60. package/dist/subtitles/srt-parser.d.ts.map +1 -0
  61. package/dist/subtitles/srt-parser.js +28 -0
  62. package/dist/subtitles/srt-parser.js.map +1 -0
  63. package/dist/subtitles/srt-writer.d.ts +4 -0
  64. package/dist/subtitles/srt-writer.d.ts.map +1 -0
  65. package/dist/subtitles/srt-writer.js +28 -0
  66. package/dist/subtitles/srt-writer.js.map +1 -0
  67. package/dist/subtitles/subtitle-generator.d.ts +9 -0
  68. package/dist/subtitles/subtitle-generator.d.ts.map +1 -0
  69. package/dist/subtitles/subtitle-generator.js +30 -0
  70. package/dist/subtitles/subtitle-generator.js.map +1 -0
  71. package/dist/subtitles/vtt-writer.d.ts +4 -0
  72. package/dist/subtitles/vtt-writer.d.ts.map +1 -0
  73. package/dist/subtitles/vtt-writer.js +28 -0
  74. package/dist/subtitles/vtt-writer.js.map +1 -0
  75. package/dist/types/render.d.ts +41 -0
  76. package/dist/types/render.d.ts.map +1 -0
  77. package/dist/types/render.js +17 -0
  78. package/dist/types/render.js.map +1 -0
  79. package/dist/types/speed.d.ts +54 -0
  80. package/dist/types/speed.d.ts.map +1 -0
  81. package/dist/types/speed.js +2 -0
  82. package/dist/types/speed.js.map +1 -0
  83. package/dist/types/subtitle.d.ts +31 -0
  84. package/dist/types/subtitle.d.ts.map +1 -0
  85. package/dist/types/subtitle.js +2 -0
  86. package/dist/types/subtitle.js.map +1 -0
  87. package/dist/types/trace.d.ts +103 -0
  88. package/dist/types/trace.d.ts.map +1 -0
  89. package/dist/types/trace.js +4 -0
  90. package/dist/types/trace.js.map +1 -0
  91. package/dist/types/voiceover.d.ts +42 -0
  92. package/dist/types/voiceover.d.ts.map +1 -0
  93. package/dist/types/voiceover.js +2 -0
  94. package/dist/types/voiceover.js.map +1 -0
  95. package/dist/utils/ffmpeg.d.ts +7 -0
  96. package/dist/utils/ffmpeg.d.ts.map +1 -0
  97. package/dist/utils/ffmpeg.js +24 -0
  98. package/dist/utils/ffmpeg.js.map +1 -0
  99. package/dist/voiceover/providers/elevenlabs.d.ts +12 -0
  100. package/dist/voiceover/providers/elevenlabs.d.ts.map +1 -0
  101. package/dist/voiceover/providers/elevenlabs.js +55 -0
  102. package/dist/voiceover/providers/elevenlabs.js.map +1 -0
  103. package/dist/voiceover/providers/openai.d.ts +14 -0
  104. package/dist/voiceover/providers/openai.d.ts.map +1 -0
  105. package/dist/voiceover/providers/openai.js +53 -0
  106. package/dist/voiceover/providers/openai.js.map +1 -0
  107. package/dist/voiceover/voiceover-processor.d.ts +9 -0
  108. package/dist/voiceover/voiceover-processor.d.ts.map +1 -0
  109. package/dist/voiceover/voiceover-processor.js +88 -0
  110. package/dist/voiceover/voiceover-processor.js.map +1 -0
  111. package/package.json +87 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/types/trace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export function toMonotonic(ms) {
2
+ return ms;
3
+ }
4
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/types/trace.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,OAAO,EAAiB,CAAA;AAC1B,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { SubtitleEntry, SubtitledTrace } from './subtitle';
2
+ /** A chunk of synthesized audio */
3
+ export interface AudioSegment {
4
+ data: Buffer;
5
+ durationMs: number;
6
+ format: {
7
+ sampleRate: number;
8
+ channels: number;
9
+ codec: string;
10
+ };
11
+ }
12
+ /** Options for a single TTS synthesis call */
13
+ export interface TtsOptions {
14
+ voice?: string;
15
+ speed?: number;
16
+ format?: 'mp3' | 'wav' | 'opus' | 'pcm';
17
+ locale?: string;
18
+ }
19
+ /** The contract every TTS provider must implement */
20
+ export interface TtsProvider {
21
+ readonly name: string;
22
+ synthesize(text: string, options?: TtsOptions): Promise<AudioSegment>;
23
+ estimateDurationMs(text: string, options?: TtsOptions): number;
24
+ isAvailable(): Promise<boolean>;
25
+ dispose(): Promise<void>;
26
+ }
27
+ /** A voiceover entry matched to a subtitle */
28
+ export interface VoiceoverEntry {
29
+ subtitle: SubtitleEntry;
30
+ audio: AudioSegment;
31
+ outputStartMs: number;
32
+ outputEndMs: number;
33
+ }
34
+ /** Trace after voiceover has been generated */
35
+ export interface VoiceoveredTrace extends SubtitledTrace {
36
+ voiceover: {
37
+ entries: VoiceoverEntry[];
38
+ audioTrackPath: string;
39
+ totalDurationMs: number;
40
+ };
41
+ }
42
+ //# sourceMappingURL=voiceover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voiceover.d.ts","sourceRoot":"","sources":["../../src/types/voiceover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE/D,mCAAmC;AACnC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE;QACN,UAAU,EAAE,MAAM,CAAA;QAClB,QAAQ,EAAE,MAAM,CAAA;QAChB,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,8CAA8C;AAC9C,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAA;IACvC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACrE,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAC9D,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAED,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,aAAa,CAAA;IACvB,KAAK,EAAE,YAAY,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,+CAA+C;AAC/C,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD,SAAS,EAAE;QACT,OAAO,EAAE,cAAc,EAAE,CAAA;QACzB,cAAc,EAAE,MAAM,CAAA;QACtB,eAAe,EAAE,MAAM,CAAA;KACxB,CAAA;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=voiceover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voiceover.js","sourceRoot":"","sources":["../../src/types/voiceover.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Assert that both `ffmpeg` and `ffprobe` are available on the system PATH.
3
+ * Throws a descriptive error if either binary is missing, so the user gets
4
+ * a clear message instead of a cryptic ENOENT later in the pipeline.
5
+ */
6
+ export declare function assertFfmpegAvailable(): void;
7
+ //# sourceMappingURL=ffmpeg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffmpeg.d.ts","sourceRoot":"","sources":["../../src/utils/ffmpeg.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAiB5C"}
@@ -0,0 +1,24 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ /**
3
+ * Assert that both `ffmpeg` and `ffprobe` are available on the system PATH.
4
+ * Throws a descriptive error if either binary is missing, so the user gets
5
+ * a clear message instead of a cryptic ENOENT later in the pipeline.
6
+ */
7
+ export function assertFfmpegAvailable() {
8
+ for (const bin of ['ffmpeg', 'ffprobe']) {
9
+ try {
10
+ execFileSync(bin, ['-version'], { stdio: 'pipe' });
11
+ }
12
+ catch (error) {
13
+ const code = error.code;
14
+ if (code === 'ENOENT') {
15
+ throw new Error(`"${bin}" is not installed or not on PATH. ` +
16
+ `Install ffmpeg (https://ffmpeg.org/download.html) and ensure both ffmpeg and ffprobe are accessible.`);
17
+ }
18
+ // If the binary exists but returned a non-zero exit code, that's fine —
19
+ // it means the binary is present. Some ffmpeg builds exit(1) for -version
20
+ // on certain platforms, which is acceptable.
21
+ }
22
+ }
23
+ }
24
+ //# sourceMappingURL=ffmpeg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ffmpeg.js","sourceRoot":"","sources":["../../src/utils/ffmpeg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD;;;;GAIG;AACH,MAAM,UAAU,qBAAqB;IACnC,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAU,EAAE,CAAC;QACjD,IAAI,CAAC;YACH,YAAY,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QACpD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAA;YAClD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CACb,IAAI,GAAG,qCAAqC;oBAC1C,sGAAsG,CACzG,CAAA;YACH,CAAC;YACD,wEAAwE;YACxE,0EAA0E;YAC1E,6CAA6C;QAC/C,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { TtsProvider } from '../../types/voiceover';
2
+ export interface ElevenLabsProviderConfig {
3
+ apiKey?: string;
4
+ voiceId?: string;
5
+ modelId?: string;
6
+ }
7
+ /**
8
+ * ElevenLabs TTS provider.
9
+ * Requires `@elevenlabs/elevenlabs-js` as a peer dependency.
10
+ */
11
+ export declare function ElevenLabsProvider(config?: ElevenLabsProviderConfig): TtsProvider;
12
+ //# sourceMappingURL=elevenlabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elevenlabs.d.ts","sourceRoot":"","sources":["../../../src/voiceover/providers/elevenlabs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA4B,MAAM,uBAAuB,CAAA;AAElF,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAgBD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,GAAE,wBAA6B,GAAG,WAAW,CAsDrF"}
@@ -0,0 +1,55 @@
1
+ const DEFAULT_VOICE_ID = 'onwK4e9ZLuTAKqWW03F9'; // Daniel
2
+ const DEFAULT_MODEL_ID = 'eleven_multilingual_v2';
3
+ /**
4
+ * ElevenLabs TTS provider.
5
+ * Requires `@elevenlabs/elevenlabs-js` as a peer dependency.
6
+ */
7
+ export function ElevenLabsProvider(config = {}) {
8
+ const apiKey = config.apiKey ?? process.env.ELEVENLABS_API_KEY;
9
+ const voiceId = config.voiceId ?? DEFAULT_VOICE_ID;
10
+ const modelId = config.modelId ?? DEFAULT_MODEL_ID;
11
+ let client = null;
12
+ async function getClient() {
13
+ if (client)
14
+ return client;
15
+ const { ElevenLabsClient: ELClient } = await import('@elevenlabs/elevenlabs-js');
16
+ client = new ELClient({ apiKey });
17
+ return client;
18
+ }
19
+ return {
20
+ name: 'elevenlabs',
21
+ async synthesize(text, _options) {
22
+ const el = await getClient();
23
+ const audio = await el.textToSpeech.convert(voiceId, {
24
+ text,
25
+ modelId,
26
+ outputFormat: 'mp3_44100_128',
27
+ });
28
+ const reader = audio.getReader();
29
+ const chunks = [];
30
+ while (true) {
31
+ const { done, value } = await reader.read();
32
+ if (done)
33
+ break;
34
+ chunks.push(value);
35
+ }
36
+ const data = Buffer.concat(chunks);
37
+ return {
38
+ data,
39
+ durationMs: 0, // Will be measured by voiceover-processor via ffprobe
40
+ format: { sampleRate: 44100, channels: 1, codec: 'mp3' },
41
+ };
42
+ },
43
+ estimateDurationMs(text) {
44
+ const words = text.split(/\s+/).length;
45
+ return (words / 150) * 60_000;
46
+ },
47
+ async isAvailable() {
48
+ return !!apiKey;
49
+ },
50
+ async dispose() {
51
+ client = null;
52
+ },
53
+ };
54
+ }
55
+ //# sourceMappingURL=elevenlabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elevenlabs.js","sourceRoot":"","sources":["../../../src/voiceover/providers/elevenlabs.ts"],"names":[],"mappings":"AAQA,MAAM,gBAAgB,GAAG,sBAAsB,CAAA,CAAC,SAAS;AACzD,MAAM,gBAAgB,GAAG,wBAAwB,CAAA;AAajD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAmC,EAAE;IACtE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAA;IAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,gBAAgB,CAAA;IAClD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,gBAAgB,CAAA;IAElD,IAAI,MAAM,GAA4B,IAAI,CAAA;IAE1C,KAAK,UAAU,SAAS;QACtB,IAAI,MAAM;YAAE,OAAO,MAAM,CAAA;QACzB,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAA;QAChF,MAAM,GAAG,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAgC,CAAA;QAChE,OAAO,MAAM,CAAA;IACf,CAAC;IAED,OAAO;QACL,IAAI,EAAE,YAAY;QAElB,KAAK,CAAC,UAAU,CAAC,IAAY,EAAE,QAAqB;YAClD,MAAM,EAAE,GAAG,MAAM,SAAS,EAAE,CAAA;YAC5B,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE;gBACnD,IAAI;gBACJ,OAAO;gBACP,YAAY,EAAE,eAAe;aAC9B,CAAC,CAAA;YAEF,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,EAAE,CAAA;YAChC,MAAM,MAAM,GAAiB,EAAE,CAAA;YAC/B,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;gBAC3C,IAAI,IAAI;oBAAE,MAAK;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACpB,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YAClC,OAAO;gBACL,IAAI;gBACJ,UAAU,EAAE,CAAC,EAAE,sDAAsD;gBACrE,MAAM,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE;aACzD,CAAA;QACH,CAAC;QAED,kBAAkB,CAAC,IAAY;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAA;YACtC,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,MAAM,CAAA;QAC/B,CAAC;QAED,KAAK,CAAC,WAAW;YACf,OAAO,CAAC,CAAC,MAAM,CAAA;QACjB,CAAC;QAED,KAAK,CAAC,OAAO;YACX,MAAM,GAAG,IAAI,CAAA;QACf,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { TtsProvider } from '../../types/voiceover';
2
+ export interface OpenAIProviderConfig {
3
+ apiKey?: string;
4
+ voice?: string;
5
+ model?: string;
6
+ speed?: number;
7
+ instructions?: string;
8
+ }
9
+ /**
10
+ * OpenAI TTS provider.
11
+ * Requires `openai` as a peer dependency.
12
+ */
13
+ export declare function OpenAIProvider(config?: OpenAIProviderConfig): TtsProvider;
14
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/voiceover/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA4B,MAAM,uBAAuB,CAAA;AAElF,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAWD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,GAAE,oBAAyB,GAAG,WAAW,CAsD7E"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * OpenAI TTS provider.
3
+ * Requires `openai` as a peer dependency.
4
+ */
5
+ export function OpenAIProvider(config = {}) {
6
+ const apiKey = config.apiKey ?? process.env.OPENAI_API_KEY;
7
+ const voice = config.voice ?? 'nova';
8
+ const model = config.model ?? 'gpt-4o-mini-tts';
9
+ const speed = config.speed ?? 1.0;
10
+ const instructions = config.instructions;
11
+ let client = null;
12
+ async function getClient() {
13
+ if (client)
14
+ return client;
15
+ const OpenAI = (await import('openai')).default;
16
+ client = new OpenAI({ apiKey });
17
+ return client;
18
+ }
19
+ return {
20
+ name: 'openai',
21
+ async synthesize(text, options) {
22
+ const openai = await getClient();
23
+ const params = {
24
+ model,
25
+ voice: options?.voice ?? voice,
26
+ input: text,
27
+ speed: options?.speed ?? speed,
28
+ response_format: 'mp3',
29
+ };
30
+ if (instructions)
31
+ params.instructions = instructions;
32
+ const response = await openai.audio.speech.create(params);
33
+ const data = Buffer.from(await response.arrayBuffer());
34
+ return {
35
+ data,
36
+ durationMs: 0,
37
+ format: { sampleRate: 24000, channels: 1, codec: 'mp3' },
38
+ };
39
+ },
40
+ estimateDurationMs(text, options) {
41
+ const spd = options?.speed ?? speed;
42
+ const words = text.split(/\s+/).length;
43
+ return (words / (150 * spd)) * 60_000;
44
+ },
45
+ async isAvailable() {
46
+ return !!apiKey;
47
+ },
48
+ async dispose() {
49
+ client = null;
50
+ },
51
+ };
52
+ }
53
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/voiceover/providers/openai.ts"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,SAA+B,EAAE;IAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAA;IACpC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,iBAAiB,CAAA;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,GAAG,CAAA;IACjC,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAA;IAExC,IAAI,MAAM,GAAwB,IAAI,CAAA;IAEtC,KAAK,UAAU,SAAS;QACtB,IAAI,MAAM;YAAE,OAAO,MAAM,CAAA;QACzB,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;QAC/C,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,MAAM,EAAE,CAA4B,CAAA;QAC1D,OAAO,MAAM,CAAA;IACf,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ;QAEd,KAAK,CAAC,UAAU,CAAC,IAAY,EAAE,OAAoB;YACjD,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAA;YAChC,MAAM,MAAM,GAA4B;gBACtC,KAAK;gBACL,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK;gBAC9B,KAAK,EAAE,IAAI;gBACX,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK;gBAC9B,eAAe,EAAE,KAAK;aACvB,CAAA;YACD,IAAI,YAAY;gBAAE,MAAM,CAAC,YAAY,GAAG,YAAY,CAAA;YAEpD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YACzD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;YAEtD,OAAO;gBACL,IAAI;gBACJ,UAAU,EAAE,CAAC;gBACb,MAAM,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE;aACzD,CAAA;QACH,CAAC;QAED,kBAAkB,CAAC,IAAY,EAAE,OAAoB;YACnD,MAAM,GAAG,GAAG,OAAO,EAAE,KAAK,IAAI,KAAK,CAAA;YACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAA;YACtC,OAAO,CAAC,KAAK,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,MAAM,CAAA;QACvC,CAAC;QAED,KAAK,CAAC,WAAW;YACf,OAAO,CAAC,CAAC,MAAM,CAAA;QACjB,CAAC;QAED,KAAK,CAAC,OAAO;YACX,MAAM,GAAG,IAAI,CAAA;QACf,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { SubtitledTrace } from '../types/subtitle';
2
+ import type { TtsProvider, VoiceoveredTrace } from '../types/voiceover';
3
+ /**
4
+ * Generate voiceover audio from subtitles using a TTS provider.
5
+ * Produces individual audio segments, pads with silence to match timing,
6
+ * and concatenates into a single audio track.
7
+ */
8
+ export declare function generateVoiceover(trace: SubtitledTrace, provider: TtsProvider, tmpDir: string): Promise<VoiceoveredTrace>;
9
+ //# sourceMappingURL=voiceover-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voiceover-processor.d.ts","sourceRoot":"","sources":["../../src/voiceover/voiceover-processor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAkB,MAAM,oBAAoB,CAAA;AAuBvF;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,CAAC,CAuE3B"}
@@ -0,0 +1,88 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { execFileSync } from 'node:child_process';
4
+ function getAudioDurationMs(filePath) {
5
+ const output = execFileSync('ffprobe', [
6
+ '-v', 'quiet',
7
+ '-show_entries', 'format=duration',
8
+ '-of', 'csv=p=0',
9
+ filePath,
10
+ ]).toString().trim();
11
+ return Math.round(Number(output) * 1000);
12
+ }
13
+ function generateSilence(durationMs, outputPath, sampleRate = 24000) {
14
+ const durationSec = Math.max(0.01, durationMs / 1000);
15
+ execFileSync('ffmpeg', [
16
+ '-y', '-f', 'lavfi',
17
+ '-i', `anullsrc=r=${sampleRate}:cl=mono`,
18
+ '-t', String(durationSec),
19
+ '-c:a', 'libmp3lame', '-q:a', '9',
20
+ outputPath,
21
+ ], { stdio: 'pipe' });
22
+ }
23
+ /**
24
+ * Generate voiceover audio from subtitles using a TTS provider.
25
+ * Produces individual audio segments, pads with silence to match timing,
26
+ * and concatenates into a single audio track.
27
+ */
28
+ export async function generateVoiceover(trace, provider, tmpDir) {
29
+ fs.mkdirSync(tmpDir, { recursive: true });
30
+ const entries = [];
31
+ const segmentFiles = [];
32
+ let cursor = 0;
33
+ for (const subtitle of trace.subtitles) {
34
+ // Insert silence for gap before this segment
35
+ if (subtitle.startMs > cursor) {
36
+ const silencePath = path.join(tmpDir, `silence-${subtitle.index}.mp3`);
37
+ generateSilence(subtitle.startMs - cursor, silencePath);
38
+ segmentFiles.push(silencePath);
39
+ }
40
+ // Generate TTS
41
+ const segPath = path.join(tmpDir, `seg-${subtitle.index}.mp3`);
42
+ const audio = await provider.synthesize(subtitle.text);
43
+ fs.writeFileSync(segPath, audio.data);
44
+ const audioDuration = getAudioDurationMs(segPath);
45
+ const windowDuration = subtitle.endMs - subtitle.startMs;
46
+ if (audioDuration < windowDuration) {
47
+ segmentFiles.push(segPath);
48
+ const padPath = path.join(tmpDir, `pad-${subtitle.index}.mp3`);
49
+ generateSilence(windowDuration - audioDuration, padPath);
50
+ segmentFiles.push(padPath);
51
+ cursor = subtitle.endMs;
52
+ }
53
+ else {
54
+ segmentFiles.push(segPath);
55
+ cursor = subtitle.startMs + audioDuration;
56
+ }
57
+ entries.push({
58
+ subtitle,
59
+ audio,
60
+ outputStartMs: subtitle.startMs,
61
+ outputEndMs: Math.max(subtitle.endMs, subtitle.startMs + audioDuration),
62
+ });
63
+ }
64
+ // Concat all segments into single audio track
65
+ const concatList = path.join(tmpDir, 'concat.txt');
66
+ fs.writeFileSync(concatList, segmentFiles.map((f) => `file '${f}'`).join('\n'));
67
+ const audioTrackPath = path.join(tmpDir, 'voiceover.mp3');
68
+ if (segmentFiles.length > 0) {
69
+ execFileSync('ffmpeg', [
70
+ '-y', '-f', 'concat', '-safe', '0',
71
+ '-i', concatList,
72
+ '-c:a', 'libmp3lame', '-q:a', '2',
73
+ audioTrackPath,
74
+ ], { stdio: 'pipe' });
75
+ }
76
+ const totalDurationMs = segmentFiles.length > 0
77
+ ? getAudioDurationMs(audioTrackPath)
78
+ : 0;
79
+ return {
80
+ ...trace,
81
+ voiceover: {
82
+ entries,
83
+ audioTrackPath,
84
+ totalDurationMs,
85
+ },
86
+ };
87
+ }
88
+ //# sourceMappingURL=voiceover-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voiceover-processor.js","sourceRoot":"","sources":["../../src/voiceover/voiceover-processor.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "playwright-recast",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Fluent pipeline library for processing Playwright traces into polished demo videos — TTS voiceover, subtitles, speed control, and zoom.",
6
+ "license": "MIT",
7
+ "author": "Patrik Szewczyk <Patrik.Szewczyk@gmail.com>",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/ThePatriczek/playwright-recast.git"
11
+ },
12
+ "homepage": "https://github.com/ThePatriczek/playwright-recast",
13
+ "keywords": [
14
+ "playwright",
15
+ "trace",
16
+ "video",
17
+ "demo",
18
+ "tts",
19
+ "voiceover",
20
+ "subtitles",
21
+ "srt",
22
+ "bdd",
23
+ "automation"
24
+ ],
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "bin": {
28
+ "playwright-recast": "./dist/cli.js"
29
+ },
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "./helpers": {
36
+ "types": "./dist/helpers.d.ts",
37
+ "default": "./dist/helpers.js"
38
+ },
39
+ "./providers/openai": {
40
+ "types": "./dist/voiceover/providers/openai.d.ts",
41
+ "default": "./dist/voiceover/providers/openai.js"
42
+ },
43
+ "./providers/elevenlabs": {
44
+ "types": "./dist/voiceover/providers/elevenlabs.d.ts",
45
+ "default": "./dist/voiceover/providers/elevenlabs.js"
46
+ }
47
+ },
48
+ "files": [
49
+ "dist",
50
+ "README.md",
51
+ "LICENSE"
52
+ ],
53
+ "scripts": {
54
+ "build": "tsc",
55
+ "test": "vitest run",
56
+ "test:watch": "vitest watch",
57
+ "typecheck": "tsc --noEmit",
58
+ "prepublishOnly": "npm run build"
59
+ },
60
+ "dependencies": {
61
+ "fflate": "^0.8.2"
62
+ },
63
+ "peerDependencies": {
64
+ "@playwright/test": ">=1.40.0",
65
+ "openai": ">=5.0.0",
66
+ "@elevenlabs/elevenlabs-js": ">=2.0.0"
67
+ },
68
+ "peerDependenciesMeta": {
69
+ "@playwright/test": {
70
+ "optional": true
71
+ },
72
+ "openai": {
73
+ "optional": true
74
+ },
75
+ "@elevenlabs/elevenlabs-js": {
76
+ "optional": true
77
+ }
78
+ },
79
+ "devDependencies": {
80
+ "@elevenlabs/elevenlabs-js": "^2.40.0",
81
+ "@playwright/test": "^1.58.0",
82
+ "@types/node": "^22.0.0",
83
+ "openai": "^6.32.0",
84
+ "typescript": "^5.9.0",
85
+ "vitest": "^4.0.0"
86
+ }
87
+ }