recordable 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 (140) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +303 -0
  3. package/dist/actions.d.ts +140 -0
  4. package/dist/actions.d.ts.map +1 -0
  5. package/dist/actions.js +184 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/audio/track.d.ts +45 -0
  8. package/dist/audio/track.d.ts.map +1 -0
  9. package/dist/audio/track.js +61 -0
  10. package/dist/audio/track.js.map +1 -0
  11. package/dist/browser/cursor.d.ts +33 -0
  12. package/dist/browser/cursor.d.ts.map +1 -0
  13. package/dist/browser/cursor.js +118 -0
  14. package/dist/browser/cursor.js.map +1 -0
  15. package/dist/browser/dom.d.ts +31 -0
  16. package/dist/browser/dom.d.ts.map +1 -0
  17. package/dist/browser/dom.js +134 -0
  18. package/dist/browser/dom.js.map +1 -0
  19. package/dist/browser/play-button.d.ts +11 -0
  20. package/dist/browser/play-button.d.ts.map +1 -0
  21. package/dist/browser/play-button.js +87 -0
  22. package/dist/browser/play-button.js.map +1 -0
  23. package/dist/browser/runtime.d.ts +66 -0
  24. package/dist/browser/runtime.d.ts.map +1 -0
  25. package/dist/browser/runtime.js +271 -0
  26. package/dist/browser/runtime.js.map +1 -0
  27. package/dist/cli.d.ts +3 -0
  28. package/dist/cli.d.ts.map +1 -0
  29. package/dist/cli.js +131 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/compose/mix.d.ts +13 -0
  32. package/dist/compose/mix.d.ts.map +1 -0
  33. package/dist/compose/mix.js +50 -0
  34. package/dist/compose/mix.js.map +1 -0
  35. package/dist/compose/recordable.d.ts +149 -0
  36. package/dist/compose/recordable.d.ts.map +1 -0
  37. package/dist/compose/recordable.js +337 -0
  38. package/dist/compose/recordable.js.map +1 -0
  39. package/dist/compose/session.d.ts +38 -0
  40. package/dist/compose/session.d.ts.map +1 -0
  41. package/dist/compose/session.js +122 -0
  42. package/dist/compose/session.js.map +1 -0
  43. package/dist/config.d.ts +93 -0
  44. package/dist/config.d.ts.map +1 -0
  45. package/dist/config.js +64 -0
  46. package/dist/config.js.map +1 -0
  47. package/dist/errors.d.ts +13 -0
  48. package/dist/errors.d.ts.map +1 -0
  49. package/dist/errors.js +21 -0
  50. package/dist/errors.js.map +1 -0
  51. package/dist/ffmpeg.d.ts +8 -0
  52. package/dist/ffmpeg.d.ts.map +1 -0
  53. package/dist/ffmpeg.js +55 -0
  54. package/dist/ffmpeg.js.map +1 -0
  55. package/dist/formats/json.d.ts +12 -0
  56. package/dist/formats/json.d.ts.map +1 -0
  57. package/dist/formats/json.js +20 -0
  58. package/dist/formats/json.js.map +1 -0
  59. package/dist/formats/markdown/method.d.ts +25 -0
  60. package/dist/formats/markdown/method.d.ts.map +1 -0
  61. package/dist/formats/markdown/method.js +48 -0
  62. package/dist/formats/markdown/method.js.map +1 -0
  63. package/dist/formats/markdown/parse.d.ts +44 -0
  64. package/dist/formats/markdown/parse.d.ts.map +1 -0
  65. package/dist/formats/markdown/parse.js +143 -0
  66. package/dist/formats/markdown/parse.js.map +1 -0
  67. package/dist/fs.d.ts +9 -0
  68. package/dist/fs.d.ts.map +1 -0
  69. package/dist/fs.js +30 -0
  70. package/dist/fs.js.map +1 -0
  71. package/dist/index.d.ts +10 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +6 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/logger.d.ts +21 -0
  76. package/dist/logger.d.ts.map +1 -0
  77. package/dist/logger.js +45 -0
  78. package/dist/logger.js.map +1 -0
  79. package/dist/schema.d.ts +5 -0
  80. package/dist/schema.d.ts.map +1 -0
  81. package/dist/schema.js +100 -0
  82. package/dist/schema.js.map +1 -0
  83. package/dist/script.d.ts +21 -0
  84. package/dist/script.d.ts.map +1 -0
  85. package/dist/script.js +26 -0
  86. package/dist/script.js.map +1 -0
  87. package/dist/targets.d.ts +6 -0
  88. package/dist/targets.d.ts.map +1 -0
  89. package/dist/targets.js +13 -0
  90. package/dist/targets.js.map +1 -0
  91. package/dist/timing.d.ts +41 -0
  92. package/dist/timing.d.ts.map +1 -0
  93. package/dist/timing.js +149 -0
  94. package/dist/timing.js.map +1 -0
  95. package/dist/utils.d.ts +3 -0
  96. package/dist/utils.d.ts.map +1 -0
  97. package/dist/utils.js +8 -0
  98. package/dist/utils.js.map +1 -0
  99. package/dist/validate.d.ts +8 -0
  100. package/dist/validate.d.ts.map +1 -0
  101. package/dist/validate.js +54 -0
  102. package/dist/validate.js.map +1 -0
  103. package/dist/video/recorder.d.ts +57 -0
  104. package/dist/video/recorder.d.ts.map +1 -0
  105. package/dist/video/recorder.js +238 -0
  106. package/dist/video/recorder.js.map +1 -0
  107. package/dist/video/stitch.d.ts +15 -0
  108. package/dist/video/stitch.d.ts.map +1 -0
  109. package/dist/video/stitch.js +111 -0
  110. package/dist/video/stitch.js.map +1 -0
  111. package/dist/voiceover/alignment.d.ts +14 -0
  112. package/dist/voiceover/alignment.d.ts.map +1 -0
  113. package/dist/voiceover/alignment.js +13 -0
  114. package/dist/voiceover/alignment.js.map +1 -0
  115. package/dist/voiceover/cache.d.ts +22 -0
  116. package/dist/voiceover/cache.d.ts.map +1 -0
  117. package/dist/voiceover/cache.js +55 -0
  118. package/dist/voiceover/cache.js.map +1 -0
  119. package/dist/voiceover/compile.d.ts +35 -0
  120. package/dist/voiceover/compile.d.ts.map +1 -0
  121. package/dist/voiceover/compile.js +194 -0
  122. package/dist/voiceover/compile.js.map +1 -0
  123. package/dist/voiceover/elevenlabs.d.ts +16 -0
  124. package/dist/voiceover/elevenlabs.d.ts.map +1 -0
  125. package/dist/voiceover/elevenlabs.js +66 -0
  126. package/dist/voiceover/elevenlabs.js.map +1 -0
  127. package/dist/voiceover/index.d.ts +7 -0
  128. package/dist/voiceover/index.d.ts.map +1 -0
  129. package/dist/voiceover/index.js +8 -0
  130. package/dist/voiceover/index.js.map +1 -0
  131. package/dist/voiceover/mock.d.ts +15 -0
  132. package/dist/voiceover/mock.d.ts.map +1 -0
  133. package/dist/voiceover/mock.js +41 -0
  134. package/dist/voiceover/mock.js.map +1 -0
  135. package/dist/voiceover/types.d.ts +31 -0
  136. package/dist/voiceover/types.d.ts.map +1 -0
  137. package/dist/voiceover/types.js +10 -0
  138. package/dist/voiceover/types.js.map +1 -0
  139. package/package.json +86 -0
  140. package/recordable.schema.json +738 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/voiceover/mock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAYvE,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,eAAgB,YAAW,WAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,GAAE,WAAgB;IAE7C,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,YAAiB,GAAG,OAAO,CAAC,SAAS,CAAC;CAgB7E;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,SAAO,GAAG,MAAM,CAmBvE"}
@@ -0,0 +1,41 @@
1
+ export class MockTTSProvider {
2
+ opts;
3
+ constructor(opts = {}) {
4
+ this.opts = opts;
5
+ }
6
+ async synthesize(text, _opts = {}) {
7
+ const msPerChar = this.opts.msPerChar ?? 55;
8
+ const sampleRate = this.opts.sampleRate ?? 8000;
9
+ const chars = [...text];
10
+ const startMs = chars.map((_, i) => i * msPerChar);
11
+ const endMs = chars.map((_, i) => (i + 1) * msPerChar);
12
+ const durationMs = chars.length * msPerChar;
13
+ return {
14
+ audio: silentWav(durationMs, sampleRate),
15
+ format: "wav",
16
+ durationMs,
17
+ alignment: { chars, startMs, endMs },
18
+ };
19
+ }
20
+ }
21
+ /** Build a valid silent 16-bit mono WAV of `durationMs` — ffmpeg-compatible. */
22
+ export function silentWav(durationMs, sampleRate = 8000) {
23
+ const numSamples = Math.max(0, Math.round((durationMs / 1000) * sampleRate));
24
+ const dataSize = numSamples * 2; // 16-bit mono
25
+ const buf = Buffer.alloc(44 + dataSize); // samples already zero = silence
26
+ buf.write("RIFF", 0, "ascii");
27
+ buf.writeUInt32LE(36 + dataSize, 4);
28
+ buf.write("WAVE", 8, "ascii");
29
+ buf.write("fmt ", 12, "ascii");
30
+ buf.writeUInt32LE(16, 16); // PCM fmt chunk size
31
+ buf.writeUInt16LE(1, 20); // audioFormat = PCM
32
+ buf.writeUInt16LE(1, 22); // channels = mono
33
+ buf.writeUInt32LE(sampleRate, 24);
34
+ buf.writeUInt32LE(sampleRate * 2, 28); // byteRate
35
+ buf.writeUInt16LE(2, 32); // blockAlign
36
+ buf.writeUInt16LE(16, 34); // bitsPerSample
37
+ buf.write("data", 36, "ascii");
38
+ buf.writeUInt32LE(dataSize, 40);
39
+ return buf;
40
+ }
41
+ //# sourceMappingURL=mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../../src/voiceover/mock.ts"],"names":[],"mappings":"AAmBA,MAAM,OAAO,eAAe;IACG;IAA7B,YAA6B,OAAoB,EAAE;QAAtB,SAAI,GAAJ,IAAI,CAAkB;IAAG,CAAC;IAEvD,KAAK,CAAC,UAAU,CAAC,IAAY,EAAE,QAAsB,EAAE;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;QAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;QAEhD,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QACxB,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QACvD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;QAE5C,OAAO;YACL,KAAK,EAAE,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC;YACxC,MAAM,EAAE,KAAK;YACb,UAAU;YACV,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;SACrC,CAAC;IACJ,CAAC;CACF;AAED,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAC,UAAkB,EAAE,UAAU,GAAG,IAAI;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,cAAc;IAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,iCAAiC;IAE1E,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9B,GAAG,CAAC,aAAa,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC;IACpC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9B,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAC/B,GAAG,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB;IAChD,GAAG,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,oBAAoB;IAC9C,GAAG,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB;IAC5C,GAAG,CAAC,aAAa,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAClC,GAAG,CAAC,aAAa,CAAC,UAAU,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW;IAClD,GAAG,CAAC,aAAa,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa;IACvC,GAAG,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB;IAC3C,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAC/B,GAAG,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAChC,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,31 @@
1
+ /** Provider-agnostic, normalised character alignment (all times in ms). */
2
+ export interface Alignment {
3
+ /** One entry per character of the synthesized text. */
4
+ chars: string[];
5
+ /** Per-character start time, ms from the clip start. */
6
+ startMs: number[];
7
+ /** Per-character end time, ms from the clip start. */
8
+ endMs: number[];
9
+ }
10
+ /** The product of one synthesis: decoded audio bytes plus timing. */
11
+ export interface TTSResult {
12
+ /** Decoded audio bytes (already base64-decoded). */
13
+ audio: Buffer;
14
+ /** Encoded format, e.g. "mp3_44100_128". */
15
+ format: string;
16
+ /** Clip duration in ms (alignment-derived when available). */
17
+ durationMs: number;
18
+ /** Character alignment, if the provider returned it. Degrade gracefully if absent. */
19
+ alignment?: Alignment;
20
+ }
21
+ /** Per-call synthesis options (reserved for future per-block overrides). */
22
+ export interface SynthOptions {
23
+ format?: string;
24
+ }
25
+ /** Turns narration text into audio + timing. The one thing add-ons implement. */
26
+ export interface TTSProvider {
27
+ synthesize(text: string, opts?: SynthOptions): Promise<TTSResult>;
28
+ }
29
+ /** File extension for an encoded format string, e.g. "mp3_44100_128" → "mp3". */
30
+ export declare function extFor(format: string): string;
31
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/voiceover/types.ts"],"names":[],"mappings":"AAMA,2EAA2E;AAC3E,MAAM,WAAW,SAAS;IACxB,uDAAuD;IACvD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,wDAAwD;IACxD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sDAAsD;IACtD,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACnE;AAED,iFAAiF;AACjF,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7C"}
@@ -0,0 +1,10 @@
1
+ // ─── TTS adapter contract ────────────────────────────────────────────────────
2
+ //
3
+ // The swappable boundary between narration text and audio+timing. A provider
4
+ // knows nothing about ffmpeg, the queue, or scheduling — it only turns text into
5
+ // sound plus optional character alignment. ElevenLabs is the first implementation.
6
+ /** File extension for an encoded format string, e.g. "mp3_44100_128" → "mp3". */
7
+ export function extFor(format) {
8
+ return format.split("_")[0] || "mp3";
9
+ }
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/voiceover/types.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,6EAA6E;AAC7E,iFAAiF;AACjF,mFAAmF;AAkCnF,iFAAiF;AACjF,MAAM,UAAU,MAAM,CAAC,MAAc;IACnC,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;AACvC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "recordable",
3
+ "version": "0.1.0",
4
+ "description": "Programmatic, repeatable browser screen recording. Script a walkthrough as a fluent chain of actions — clicks, typing, smooth zoom/scroll, an animated cursor, and manual steps like logins — and capture it to MP4.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/paragramagency/recordable.git"
8
+ },
9
+ "homepage": "https://github.com/paragramagency/recordable#readme",
10
+ "bugs": {
11
+ "url": "https://github.com/paragramagency/recordable/issues"
12
+ },
13
+ "type": "module",
14
+ "main": "./dist/index.js",
15
+ "module": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "bin": {
18
+ "recordable": "./dist/cli.js"
19
+ },
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js"
24
+ },
25
+ "./voiceover": {
26
+ "types": "./dist/voiceover/index.d.ts",
27
+ "import": "./dist/voiceover/index.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "recordable.schema.json",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsc",
38
+ "test": "tsx --test test/**/*.test.ts",
39
+ "clean": "rm -rf dist",
40
+ "gen:schema": "tsx scripts/gen-schema.ts",
41
+ "lint": "eslint .",
42
+ "lint:fix": "eslint . --fix",
43
+ "format": "prettier --write .",
44
+ "format:check": "prettier --check .",
45
+ "prepublishOnly": "npm run clean && npm run gen:schema && npm run build"
46
+ },
47
+ "keywords": [
48
+ "screen-recording",
49
+ "screencast",
50
+ "screen-capture",
51
+ "recorder",
52
+ "puppeteer",
53
+ "automation",
54
+ "browser",
55
+ "scripted",
56
+ "video",
57
+ "mp4"
58
+ ],
59
+ "author": "Cam Parry <hello@camparry.com>",
60
+ "license": "MIT",
61
+ "engines": {
62
+ "node": ">=18"
63
+ },
64
+ "dependencies": {
65
+ "@ffmpeg-installer/ffmpeg": "^1.1.0",
66
+ "gray-matter": "^4.0.3",
67
+ "json5": "^2.2.3",
68
+ "markdown-it": "^14.2.0",
69
+ "puppeteer": "^22.0.0",
70
+ "zod": "^4.4.3"
71
+ },
72
+ "devDependencies": {
73
+ "@eslint/js": "^10.0.1",
74
+ "@types/markdown-it": "^14.1.2",
75
+ "@types/node": "^20.0.0",
76
+ "eslint": "^10.5.0",
77
+ "eslint-config-prettier": "^10.1.8",
78
+ "prettier": "^3.8.4",
79
+ "tsx": "^4.0.0",
80
+ "typescript": "^5.0.0",
81
+ "typescript-eslint": "^8.62.0"
82
+ },
83
+ "optionalDependencies": {
84
+ "@elevenlabs/elevenlabs-js": "^2.0.0"
85
+ }
86
+ }