@editframe/assets 0.7.0-beta.11 → 0.7.0-beta.15

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 (50) hide show
  1. package/dist/EncodedAsset.d.ts +102 -0
  2. package/dist/EncodedAsset.js +564 -0
  3. package/dist/MP4File.d.ts +31 -0
  4. package/dist/{packages/assets/src/Probe.d.ts → Probe.d.ts} +45 -41
  5. package/dist/{packages/assets/src/Probe.js → Probe.js} +54 -5
  6. package/dist/index.d.ts +9 -0
  7. package/dist/{packages/assets/src/index.js → index.js} +6 -3
  8. package/dist/memoize.d.ts +2 -0
  9. package/dist/memoize.js +14 -0
  10. package/dist/{packages/assets/src/mp4FileWritable.d.ts → mp4FileWritable.d.ts} +1 -1
  11. package/dist/tasks/cacheImage.d.ts +1 -0
  12. package/dist/tasks/findOrCreateCaptions.d.ts +2 -0
  13. package/dist/tasks/findOrCreateCaptions.js +30 -0
  14. package/dist/tasks/generateTrack.d.ts +5 -0
  15. package/dist/{packages/assets/src/tasks → tasks}/generateTrack.js +26 -23
  16. package/dist/tasks/generateTrackFragmentIndex.d.ts +4 -0
  17. package/dist/{packages/assets/src/tasks → tasks}/generateTrackFragmentIndex.js +12 -6
  18. package/package.json +13 -10
  19. package/src/tasks/cacheImage.ts +1 -1
  20. package/src/tasks/findOrCreateCaptions.ts +18 -11
  21. package/src/tasks/generateTrack.ts +36 -31
  22. package/src/tasks/generateTrackFragmentIndex.ts +16 -9
  23. package/dist/lib/av/MP4File.cjs +0 -187
  24. package/dist/lib/util/execPromise.cjs +0 -6
  25. package/dist/lib/util/execPromise.js +0 -6
  26. package/dist/packages/assets/src/Probe.cjs +0 -224
  27. package/dist/packages/assets/src/VideoRenderOptions.cjs +0 -36
  28. package/dist/packages/assets/src/idempotentTask.cjs +0 -57
  29. package/dist/packages/assets/src/index.cjs +0 -20
  30. package/dist/packages/assets/src/index.d.ts +0 -9
  31. package/dist/packages/assets/src/md5.cjs +0 -60
  32. package/dist/packages/assets/src/mp4FileWritable.cjs +0 -21
  33. package/dist/packages/assets/src/tasks/cacheImage.cjs +0 -22
  34. package/dist/packages/assets/src/tasks/cacheImage.d.ts +0 -1
  35. package/dist/packages/assets/src/tasks/findOrCreateCaptions.cjs +0 -26
  36. package/dist/packages/assets/src/tasks/findOrCreateCaptions.d.ts +0 -1
  37. package/dist/packages/assets/src/tasks/findOrCreateCaptions.js +0 -26
  38. package/dist/packages/assets/src/tasks/generateTrack.cjs +0 -52
  39. package/dist/packages/assets/src/tasks/generateTrack.d.ts +0 -1
  40. package/dist/packages/assets/src/tasks/generateTrackFragmentIndex.cjs +0 -105
  41. package/dist/packages/assets/src/tasks/generateTrackFragmentIndex.d.ts +0 -1
  42. /package/dist/{lib/av/MP4File.js → MP4File.js} +0 -0
  43. /package/dist/{packages/assets/src/VideoRenderOptions.d.ts → VideoRenderOptions.d.ts} +0 -0
  44. /package/dist/{packages/assets/src/VideoRenderOptions.js → VideoRenderOptions.js} +0 -0
  45. /package/dist/{packages/assets/src/idempotentTask.d.ts → idempotentTask.d.ts} +0 -0
  46. /package/dist/{packages/assets/src/idempotentTask.js → idempotentTask.js} +0 -0
  47. /package/dist/{packages/assets/src/md5.d.ts → md5.d.ts} +0 -0
  48. /package/dist/{packages/assets/src/md5.js → md5.js} +0 -0
  49. /package/dist/{packages/assets/src/mp4FileWritable.js → mp4FileWritable.js} +0 -0
  50. /package/dist/{packages/assets/src/tasks → tasks}/cacheImage.js +0 -0
@@ -1,3 +1,4 @@
1
+ import { Readable } from 'node:stream';
1
2
  import * as z from "zod";
2
3
  export declare const AudioStreamSchema: z.ZodObject<{
3
4
  index: z.ZodNumber;
@@ -22,6 +23,7 @@ export declare const AudioStreamSchema: z.ZodObject<{
22
23
  bit_rate: z.ZodString;
23
24
  disposition: z.ZodRecord<z.ZodString, z.ZodUnknown>;
24
25
  }, "strip", z.ZodTypeAny, {
26
+ duration: number;
25
27
  index: number;
26
28
  codec_name: string;
27
29
  codec_long_name: string;
@@ -39,11 +41,11 @@ export declare const AudioStreamSchema: z.ZodObject<{
39
41
  start_pts: number;
40
42
  start_time: number;
41
43
  duration_ts: number;
42
- duration: number;
43
44
  bit_rate: string;
44
45
  disposition: Record<string, unknown>;
45
46
  initial_padding?: number | undefined;
46
47
  }, {
48
+ duration: number;
47
49
  index: number;
48
50
  codec_name: string;
49
51
  codec_long_name: string;
@@ -61,7 +63,6 @@ export declare const AudioStreamSchema: z.ZodObject<{
61
63
  start_pts: number;
62
64
  start_time: number;
63
65
  duration_ts: number;
64
- duration: number;
65
66
  bit_rate: string;
66
67
  disposition: Record<string, unknown>;
67
68
  initial_padding?: number | undefined;
@@ -102,10 +103,10 @@ export declare const VideoStreamSchema: z.ZodObject<{
102
103
  height: number;
103
104
  coded_width: number;
104
105
  coded_height: number;
106
+ duration?: number | undefined;
105
107
  start_pts?: number | undefined;
106
108
  start_time?: number | undefined;
107
109
  duration_ts?: number | undefined;
108
- duration?: number | undefined;
109
110
  bit_rate?: string | undefined;
110
111
  }, {
111
112
  index: number;
@@ -122,10 +123,10 @@ export declare const VideoStreamSchema: z.ZodObject<{
122
123
  height: number;
123
124
  coded_width: number;
124
125
  coded_height: number;
126
+ duration?: number | undefined;
125
127
  start_pts?: number | undefined;
126
128
  start_time?: number | undefined;
127
129
  duration_ts?: number | undefined;
128
- duration?: number | undefined;
129
130
  bit_rate?: string | undefined;
130
131
  }>;
131
132
  export type VideoStreamSchema = z.infer<typeof VideoStreamSchema>;
@@ -152,6 +153,7 @@ declare const StreamSchema: z.ZodDiscriminatedUnion<"codec_type", [z.ZodObject<{
152
153
  bit_rate: z.ZodString;
153
154
  disposition: z.ZodRecord<z.ZodString, z.ZodUnknown>;
154
155
  }, "strip", z.ZodTypeAny, {
156
+ duration: number;
155
157
  index: number;
156
158
  codec_name: string;
157
159
  codec_long_name: string;
@@ -169,11 +171,11 @@ declare const StreamSchema: z.ZodDiscriminatedUnion<"codec_type", [z.ZodObject<{
169
171
  start_pts: number;
170
172
  start_time: number;
171
173
  duration_ts: number;
172
- duration: number;
173
174
  bit_rate: string;
174
175
  disposition: Record<string, unknown>;
175
176
  initial_padding?: number | undefined;
176
177
  }, {
178
+ duration: number;
177
179
  index: number;
178
180
  codec_name: string;
179
181
  codec_long_name: string;
@@ -191,7 +193,6 @@ declare const StreamSchema: z.ZodDiscriminatedUnion<"codec_type", [z.ZodObject<{
191
193
  start_pts: number;
192
194
  start_time: number;
193
195
  duration_ts: number;
194
- duration: number;
195
196
  bit_rate: string;
196
197
  disposition: Record<string, unknown>;
197
198
  initial_padding?: number | undefined;
@@ -230,10 +231,10 @@ declare const StreamSchema: z.ZodDiscriminatedUnion<"codec_type", [z.ZodObject<{
230
231
  height: number;
231
232
  coded_width: number;
232
233
  coded_height: number;
234
+ duration?: number | undefined;
233
235
  start_pts?: number | undefined;
234
236
  start_time?: number | undefined;
235
237
  duration_ts?: number | undefined;
236
- duration?: number | undefined;
237
238
  bit_rate?: string | undefined;
238
239
  }, {
239
240
  index: number;
@@ -250,10 +251,10 @@ declare const StreamSchema: z.ZodDiscriminatedUnion<"codec_type", [z.ZodObject<{
250
251
  height: number;
251
252
  coded_width: number;
252
253
  coded_height: number;
254
+ duration?: number | undefined;
253
255
  start_pts?: number | undefined;
254
256
  start_time?: number | undefined;
255
257
  duration_ts?: number | undefined;
256
- duration?: number | undefined;
257
258
  bit_rate?: string | undefined;
258
259
  }>]>;
259
260
  export type StreamSchema = z.infer<typeof StreamSchema>;
@@ -281,6 +282,7 @@ declare const ProbeSchema: z.ZodObject<{
281
282
  bit_rate: z.ZodString;
282
283
  disposition: z.ZodRecord<z.ZodString, z.ZodUnknown>;
283
284
  }, "strip", z.ZodTypeAny, {
285
+ duration: number;
284
286
  index: number;
285
287
  codec_name: string;
286
288
  codec_long_name: string;
@@ -298,11 +300,11 @@ declare const ProbeSchema: z.ZodObject<{
298
300
  start_pts: number;
299
301
  start_time: number;
300
302
  duration_ts: number;
301
- duration: number;
302
303
  bit_rate: string;
303
304
  disposition: Record<string, unknown>;
304
305
  initial_padding?: number | undefined;
305
306
  }, {
307
+ duration: number;
306
308
  index: number;
307
309
  codec_name: string;
308
310
  codec_long_name: string;
@@ -320,7 +322,6 @@ declare const ProbeSchema: z.ZodObject<{
320
322
  start_pts: number;
321
323
  start_time: number;
322
324
  duration_ts: number;
323
- duration: number;
324
325
  bit_rate: string;
325
326
  disposition: Record<string, unknown>;
326
327
  initial_padding?: number | undefined;
@@ -359,10 +360,10 @@ declare const ProbeSchema: z.ZodObject<{
359
360
  height: number;
360
361
  coded_width: number;
361
362
  coded_height: number;
363
+ duration?: number | undefined;
362
364
  start_pts?: number | undefined;
363
365
  start_time?: number | undefined;
364
366
  duration_ts?: number | undefined;
365
- duration?: number | undefined;
366
367
  bit_rate?: string | undefined;
367
368
  }, {
368
369
  index: number;
@@ -379,10 +380,10 @@ declare const ProbeSchema: z.ZodObject<{
379
380
  height: number;
380
381
  coded_width: number;
381
382
  coded_height: number;
383
+ duration?: number | undefined;
382
384
  start_pts?: number | undefined;
383
385
  start_time?: number | undefined;
384
386
  duration_ts?: number | undefined;
385
- duration?: number | undefined;
386
387
  bit_rate?: string | undefined;
387
388
  }>]>, "many">;
388
389
  format: z.ZodObject<{
@@ -393,7 +394,7 @@ declare const ProbeSchema: z.ZodObject<{
393
394
  format_long_name: z.ZodString;
394
395
  start_time: z.ZodOptional<z.ZodString>;
395
396
  duration: z.ZodOptional<z.ZodString>;
396
- size: z.ZodString;
397
+ size: z.ZodOptional<z.ZodString>;
397
398
  bit_rate: z.ZodOptional<z.ZodString>;
398
399
  probe_score: z.ZodNumber;
399
400
  }, "strip", z.ZodTypeAny, {
@@ -402,25 +403,38 @@ declare const ProbeSchema: z.ZodObject<{
402
403
  nb_programs: number;
403
404
  format_name: string;
404
405
  format_long_name: string;
405
- size: string;
406
406
  probe_score: number;
407
- start_time?: string | undefined;
408
407
  duration?: string | undefined;
408
+ start_time?: string | undefined;
409
409
  bit_rate?: string | undefined;
410
+ size?: string | undefined;
410
411
  }, {
411
412
  filename: string;
412
413
  nb_streams: number;
413
414
  nb_programs: number;
414
415
  format_name: string;
415
416
  format_long_name: string;
416
- size: string;
417
417
  probe_score: number;
418
- start_time?: string | undefined;
419
418
  duration?: string | undefined;
419
+ start_time?: string | undefined;
420
420
  bit_rate?: string | undefined;
421
+ size?: string | undefined;
421
422
  }>;
422
423
  }, "strip", z.ZodTypeAny, {
424
+ format: {
425
+ filename: string;
426
+ nb_streams: number;
427
+ nb_programs: number;
428
+ format_name: string;
429
+ format_long_name: string;
430
+ probe_score: number;
431
+ duration?: string | undefined;
432
+ start_time?: string | undefined;
433
+ bit_rate?: string | undefined;
434
+ size?: string | undefined;
435
+ };
423
436
  streams: ({
437
+ duration: number;
424
438
  index: number;
425
439
  codec_name: string;
426
440
  codec_long_name: string;
@@ -438,7 +452,6 @@ declare const ProbeSchema: z.ZodObject<{
438
452
  start_pts: number;
439
453
  start_time: number;
440
454
  duration_ts: number;
441
- duration: number;
442
455
  bit_rate: string;
443
456
  disposition: Record<string, unknown>;
444
457
  initial_padding?: number | undefined;
@@ -457,26 +470,27 @@ declare const ProbeSchema: z.ZodObject<{
457
470
  height: number;
458
471
  coded_width: number;
459
472
  coded_height: number;
473
+ duration?: number | undefined;
460
474
  start_pts?: number | undefined;
461
475
  start_time?: number | undefined;
462
476
  duration_ts?: number | undefined;
463
- duration?: number | undefined;
464
477
  bit_rate?: string | undefined;
465
478
  })[];
479
+ }, {
466
480
  format: {
467
481
  filename: string;
468
482
  nb_streams: number;
469
483
  nb_programs: number;
470
484
  format_name: string;
471
485
  format_long_name: string;
472
- size: string;
473
486
  probe_score: number;
474
- start_time?: string | undefined;
475
487
  duration?: string | undefined;
488
+ start_time?: string | undefined;
476
489
  bit_rate?: string | undefined;
490
+ size?: string | undefined;
477
491
  };
478
- }, {
479
492
  streams: ({
493
+ duration: number;
480
494
  index: number;
481
495
  codec_name: string;
482
496
  codec_long_name: string;
@@ -494,7 +508,6 @@ declare const ProbeSchema: z.ZodObject<{
494
508
  start_pts: number;
495
509
  start_time: number;
496
510
  duration_ts: number;
497
- duration: number;
498
511
  bit_rate: string;
499
512
  disposition: Record<string, unknown>;
500
513
  initial_padding?: number | undefined;
@@ -513,24 +526,12 @@ declare const ProbeSchema: z.ZodObject<{
513
526
  height: number;
514
527
  coded_width: number;
515
528
  coded_height: number;
529
+ duration?: number | undefined;
516
530
  start_pts?: number | undefined;
517
531
  start_time?: number | undefined;
518
532
  duration_ts?: number | undefined;
519
- duration?: number | undefined;
520
533
  bit_rate?: string | undefined;
521
534
  })[];
522
- format: {
523
- filename: string;
524
- nb_streams: number;
525
- nb_programs: number;
526
- format_name: string;
527
- format_long_name: string;
528
- size: string;
529
- probe_score: number;
530
- start_time?: string | undefined;
531
- duration?: string | undefined;
532
- bit_rate?: string | undefined;
533
- };
534
535
  }>;
535
536
  export interface TrackSegment {
536
537
  cts: number;
@@ -548,6 +549,7 @@ interface AudioTrackFragmentIndex {
548
549
  sample_rate: number;
549
550
  sample_size: number;
550
551
  sample_count: number;
552
+ codec: string;
551
553
  initSegment: {
552
554
  offset: 0;
553
555
  size: number;
@@ -562,6 +564,7 @@ interface VideoTrackFragmentIndex {
562
564
  width: number;
563
565
  height: number;
564
566
  sample_count: number;
567
+ codec: string;
565
568
  initSegment: {
566
569
  offset: 0;
567
570
  size: number;
@@ -573,10 +576,12 @@ export declare class Probe {
573
576
  private absolutePath;
574
577
  data: z.infer<typeof ProbeSchema>;
575
578
  static probePath(absolutePath: string): Promise<Probe>;
579
+ static probeStream(stream: Readable): Promise<Probe>;
576
580
  constructor(absolutePath: string, rawData: any);
577
581
  get audioStreams(): AudioStreamSchema[];
578
582
  get videoStreams(): VideoStreamSchema[];
579
583
  get streams(): ({
584
+ duration: number;
580
585
  index: number;
581
586
  codec_name: string;
582
587
  codec_long_name: string;
@@ -594,7 +599,6 @@ export declare class Probe {
594
599
  start_pts: number;
595
600
  start_time: number;
596
601
  duration_ts: number;
597
- duration: number;
598
602
  bit_rate: string;
599
603
  disposition: Record<string, unknown>;
600
604
  initial_padding?: number | undefined;
@@ -613,10 +617,10 @@ export declare class Probe {
613
617
  height: number;
614
618
  coded_width: number;
615
619
  coded_height: number;
620
+ duration?: number | undefined;
616
621
  start_pts?: number | undefined;
617
622
  start_time?: number | undefined;
618
623
  duration_ts?: number | undefined;
619
- duration?: number | undefined;
620
624
  bit_rate?: string | undefined;
621
625
  })[];
622
626
  get format(): {
@@ -625,11 +629,11 @@ export declare class Probe {
625
629
  nb_programs: number;
626
630
  format_name: string;
627
631
  format_long_name: string;
628
- size: string;
629
632
  probe_score: number;
630
- start_time?: string | undefined;
631
633
  duration?: string | undefined;
634
+ start_time?: string | undefined;
632
635
  bit_rate?: string | undefined;
636
+ size?: string | undefined;
633
637
  };
634
638
  get mustReencodeAudio(): boolean;
635
639
  get mustReencodeVideo(): boolean;
@@ -641,6 +645,6 @@ export declare class Probe {
641
645
  get mustProcess(): boolean;
642
646
  get ffmpegAudioOptions(): string[];
643
647
  get ffmpegVideoOptions(): string[];
644
- createConformingReadstream(): import('stream').Readable;
648
+ createConformingReadstream(): Readable;
645
649
  }
646
650
  export {};
@@ -1,8 +1,9 @@
1
- import { spawn } from "node:child_process";
1
+ import { exec, spawn } from "node:child_process";
2
+ import { promisify } from "node:util";
2
3
  import { createReadStream } from "node:fs";
3
4
  import * as z from "zod";
4
5
  import debug from "debug";
5
- import { execPromise } from "../../../lib/util/execPromise.js";
6
+ const execPromise = promisify(exec);
6
7
  const log = debug("ef:assets:probe");
7
8
  const AudioStreamSchema = z.object({
8
9
  index: z.number(),
@@ -56,7 +57,7 @@ const ProbeFormatSchema = z.object({
56
57
  format_long_name: z.string(),
57
58
  start_time: z.string().optional(),
58
59
  duration: z.string().optional(),
59
- size: z.string(),
60
+ size: z.string().optional(),
60
61
  bit_rate: z.string().optional(),
61
62
  probe_score: z.number()
62
63
  });
@@ -82,6 +83,51 @@ class Probe {
82
83
  const json = JSON.parse(probeResult.stdout);
83
84
  return new Probe(absolutePath, json);
84
85
  }
86
+ static async probeStream(stream) {
87
+ const probeCommand = "ffprobe -i pipe:0 -v error -show_format -show_streams -of json";
88
+ log("Probing", probeCommand);
89
+ const probe = spawn(
90
+ "ffprobe",
91
+ [
92
+ "-i",
93
+ "-",
94
+ "-v",
95
+ "error",
96
+ "-show_format",
97
+ "-show_streams",
98
+ "-of",
99
+ "json"
100
+ ],
101
+ {
102
+ stdio: ["pipe", "pipe", "pipe"]
103
+ }
104
+ );
105
+ const chunks = [];
106
+ probe.stderr.on("data", (data) => {
107
+ log(data.toString());
108
+ });
109
+ probe.stdout.on("data", (data) => {
110
+ chunks.push(data);
111
+ });
112
+ stream.pipe(probe.stdin);
113
+ probe.stdin.on("error", (error) => {
114
+ log("ffprobe stdin error", error);
115
+ });
116
+ const json = await new Promise((resolve, reject) => {
117
+ probe.stdout.on("end", () => {
118
+ stream.unpipe(probe.stdin);
119
+ stream.destroy();
120
+ try {
121
+ const buffer = Buffer.concat(chunks).toString("utf8");
122
+ log("Got probe from stream", buffer);
123
+ resolve(JSON.parse(buffer));
124
+ } catch (error) {
125
+ reject(error);
126
+ }
127
+ });
128
+ });
129
+ return new Probe("pipe:0", json);
130
+ }
85
131
  get audioStreams() {
86
132
  return this.data.streams.filter(
87
133
  (stream) => stream.codec_type === "audio"
@@ -160,6 +206,9 @@ class Probe {
160
206
  ];
161
207
  }
162
208
  createConformingReadstream() {
209
+ if (this.absolutePath === "pipe:0") {
210
+ throw new Error("Cannot create conforming readstream from pipe");
211
+ }
163
212
  if (!this.mustProcess) {
164
213
  return createReadStream(this.absolutePath);
165
214
  }
@@ -171,7 +220,7 @@ class Probe {
171
220
  "-f",
172
221
  "mp4",
173
222
  "-movflags",
174
- "cmaf+frag_keyframe+empty_moov",
223
+ "cmaf+frag_keyframe+empty_moov+delay_moov",
175
224
  "pipe:1"
176
225
  ];
177
226
  log("Running ffmpeg", ffmpegConformanceArgs);
@@ -189,7 +238,7 @@ class Probe {
189
238
  "-f",
190
239
  "mp4",
191
240
  "-movflags",
192
- "frag_keyframe+empty_moov",
241
+ "frag_keyframe+empty_moov+delay_moov",
193
242
  "pipe:1"
194
243
  ];
195
244
  log("Running ffmpeg", ffmpegFragmentArgs);
@@ -0,0 +1,9 @@
1
+ export { AudioStreamSchema, VideoStreamSchema, Probe } from './Probe.ts';
2
+ export type { StreamSchema, TrackSegment, TrackFragmentIndex, } from './Probe.ts';
3
+ export { md5FilePath, md5Directory, md5ReadStream } from './md5.ts';
4
+ export { generateTrackFragmentIndex, generateTrackFragmentIndexFromPath, } from './tasks/generateTrackFragmentIndex.ts';
5
+ export { generateTrack, generateTrackFromPath } from './tasks/generateTrack.ts';
6
+ export { findOrCreateCaptions, generateCaptionDataFromPath, } from './tasks/findOrCreateCaptions.ts';
7
+ export { cacheImage } from './tasks/cacheImage.ts';
8
+ export type { TaskResult } from './idempotentTask.ts';
9
+ export { VideoRenderOptions } from './VideoRenderOptions.ts';
@@ -1,8 +1,8 @@
1
1
  import { AudioStreamSchema, Probe, VideoStreamSchema } from "./Probe.js";
2
2
  import { md5Directory, md5FilePath, md5ReadStream } from "./md5.js";
3
- import { generateTrackFragmentIndex } from "./tasks/generateTrackFragmentIndex.js";
4
- import { generateTrack } from "./tasks/generateTrack.js";
5
- import { findOrCreateCaptions } from "./tasks/findOrCreateCaptions.js";
3
+ import { generateTrackFragmentIndex, generateTrackFragmentIndexFromPath } from "./tasks/generateTrackFragmentIndex.js";
4
+ import { generateTrack, generateTrackFromPath } from "./tasks/generateTrack.js";
5
+ import { findOrCreateCaptions, generateCaptionDataFromPath } from "./tasks/findOrCreateCaptions.js";
6
6
  import { cacheImage } from "./tasks/cacheImage.js";
7
7
  import { VideoRenderOptions } from "./VideoRenderOptions.js";
8
8
  export {
@@ -12,8 +12,11 @@ export {
12
12
  VideoStreamSchema,
13
13
  cacheImage,
14
14
  findOrCreateCaptions,
15
+ generateCaptionDataFromPath,
15
16
  generateTrack,
16
17
  generateTrackFragmentIndex,
18
+ generateTrackFragmentIndexFromPath,
19
+ generateTrackFromPath,
17
20
  md5Directory,
18
21
  md5FilePath,
19
22
  md5ReadStream
@@ -0,0 +1,2 @@
1
+ /** method decorator to memoize the value of a getter */
2
+ export declare const memoize: <Target extends object, PropertyKey extends keyof Target>(_target: Target, _propertyKey: PropertyKey, descriptor: TypedPropertyDescriptor<Target[PropertyKey]>) => void;
@@ -0,0 +1,14 @@
1
+ const memoize = (_target, _propertyKey, descriptor) => {
2
+ const get = descriptor.get;
3
+ if (!get) return;
4
+ const memoized = /* @__PURE__ */ new WeakMap();
5
+ descriptor.get = function() {
6
+ if (!memoized.has(this)) {
7
+ memoized.set(this, get.call(this));
8
+ }
9
+ return memoized.get(this);
10
+ };
11
+ };
12
+ export {
13
+ memoize
14
+ };
@@ -1,4 +1,4 @@
1
1
  import { Writable } from 'node:stream';
2
- import { MP4File } from '../../../lib/av/MP4File';
2
+ import { MP4File } from './MP4File.ts';
3
3
 
4
4
  export declare const mp4FileWritable: (mp4File: MP4File) => Writable;
@@ -0,0 +1 @@
1
+ export declare const cacheImage: (cacheRoot: string, absolutePath: string) => Promise<import('../idempotentTask.ts').TaskResult>;
@@ -0,0 +1,2 @@
1
+ export declare const generateCaptionDataFromPath: (absolutePath: string) => Promise<string>;
2
+ export declare const findOrCreateCaptions: (cacheRoot: string, absolutePath: string) => Promise<import('../idempotentTask.ts').TaskResult>;
@@ -0,0 +1,30 @@
1
+ import { basename } from "node:path";
2
+ import { promisify } from "node:util";
3
+ import { exec } from "node:child_process";
4
+ import debug from "debug";
5
+ import { idempotentTask } from "../idempotentTask.js";
6
+ const execPromise = promisify(exec);
7
+ const log = debug("ef:generateCaptions");
8
+ const generateCaptionDataFromPath = async (absolutePath) => {
9
+ const command = `whisper_timestamped --language en --efficient --output_format vtt ${absolutePath}`;
10
+ log(`Running command: ${command}`);
11
+ const { stdout } = await execPromise(command);
12
+ return stdout;
13
+ };
14
+ const generateCaptionDataTask = idempotentTask({
15
+ label: "captions",
16
+ filename: (absolutePath) => `${basename(absolutePath)}.captions.json`,
17
+ runner: generateCaptionDataFromPath
18
+ });
19
+ const findOrCreateCaptions = async (cacheRoot, absolutePath) => {
20
+ try {
21
+ return await generateCaptionDataTask(cacheRoot, absolutePath);
22
+ } catch (error) {
23
+ console.trace("Error finding or creating captions", error);
24
+ throw error;
25
+ }
26
+ };
27
+ export {
28
+ findOrCreateCaptions,
29
+ generateCaptionDataFromPath
30
+ };
@@ -0,0 +1,5 @@
1
+ import { PassThrough } from 'node:stream';
2
+
3
+ export declare const generateTrackFromPath: (absolutePath: string, trackId: number) => Promise<PassThrough>;
4
+ export declare const generateTrackTask: (rootDir: string, absolutePath: string, trackId: number) => Promise<import('../idempotentTask.ts').TaskResult>;
5
+ export declare const generateTrack: (cacheRoot: string, absolutePath: string, url: string) => Promise<import('../idempotentTask.ts').TaskResult>;
@@ -1,34 +1,35 @@
1
1
  import { idempotentTask } from "../idempotentTask.js";
2
- import { MP4File } from "../../../../lib/av/MP4File.js";
2
+ import { MP4File } from "../MP4File.js";
3
3
  import debug from "debug";
4
4
  import { mp4FileWritable } from "../mp4FileWritable.js";
5
5
  import { PassThrough } from "node:stream";
6
6
  import { basename } from "node:path";
7
7
  import { Probe } from "../Probe.js";
8
+ const generateTrackFromPath = async (absolutePath, trackId) => {
9
+ const log = debug("ef:generateTrackFragment");
10
+ const probe = await Probe.probePath(absolutePath);
11
+ const readStream = probe.createConformingReadstream();
12
+ const mp4File = new MP4File();
13
+ log(`Generating track for ${absolutePath}`);
14
+ readStream.pipe(mp4FileWritable(mp4File));
15
+ await new Promise((resolve, reject) => {
16
+ readStream.on("end", resolve);
17
+ readStream.on("error", reject);
18
+ });
19
+ const trackStream = new PassThrough();
20
+ for await (const fragment of mp4File.fragmentIterator()) {
21
+ if (fragment.track !== trackId) {
22
+ continue;
23
+ }
24
+ trackStream.write(Buffer.from(fragment.data), "binary");
25
+ }
26
+ trackStream.end();
27
+ return trackStream;
28
+ };
8
29
  const generateTrackTask = idempotentTask({
9
30
  label: "track",
10
31
  filename: (absolutePath, trackId) => `${basename(absolutePath)}.track-${trackId}.mp4`,
11
- runner: async (absolutePath, trackId) => {
12
- const log = debug("ef:generateTrackFragment");
13
- const probe = await Probe.probePath(absolutePath);
14
- const readStream = probe.createConformingReadstream();
15
- const mp4File = new MP4File();
16
- log(`Generating track fragment index for ${absolutePath}`);
17
- readStream.pipe(mp4FileWritable(mp4File));
18
- await new Promise((resolve, reject) => {
19
- readStream.on("end", resolve);
20
- readStream.on("error", reject);
21
- });
22
- const trackStream = new PassThrough();
23
- for await (const fragment of mp4File.fragmentIterator()) {
24
- if (fragment.track !== trackId) {
25
- continue;
26
- }
27
- trackStream.write(Buffer.from(fragment.data), "binary");
28
- }
29
- trackStream.end();
30
- return trackStream;
31
- }
32
+ runner: generateTrackFromPath
32
33
  });
33
34
  const generateTrack = async (cacheRoot, absolutePath, url) => {
34
35
  try {
@@ -48,5 +49,7 @@ const generateTrack = async (cacheRoot, absolutePath, url) => {
48
49
  }
49
50
  };
50
51
  export {
51
- generateTrack
52
+ generateTrack,
53
+ generateTrackFromPath,
54
+ generateTrackTask
52
55
  };
@@ -0,0 +1,4 @@
1
+ import { TrackFragmentIndex } from '../Probe.ts';
2
+
3
+ export declare const generateTrackFragmentIndexFromPath: (absolutePath: string) => Promise<Record<number, TrackFragmentIndex>>;
4
+ export declare const generateTrackFragmentIndex: (cacheRoot: string, absolutePath: string) => Promise<import('../idempotentTask.ts').TaskResult>;
@@ -1,5 +1,5 @@
1
1
  import { idempotentTask } from "../idempotentTask.js";
2
- import { MP4File } from "../../../../lib/av/MP4File.js";
2
+ import { MP4File } from "../MP4File.js";
3
3
  import debug from "debug";
4
4
  import { mp4FileWritable } from "../mp4FileWritable.js";
5
5
  import { basename } from "node:path";
@@ -36,7 +36,8 @@ const generateTrackFragmentIndexFromPath = async (absolutePath) => {
36
36
  height: videoTrack.video.height,
37
37
  timescale: track.timescale,
38
38
  sample_count: videoTrack.nb_samples,
39
- duration: 0,
39
+ codec: videoTrack.codec,
40
+ duration: videoTrack.duration,
40
41
  initSegment: {
41
42
  offset: 0,
42
43
  size: fragment.data.byteLength
@@ -57,7 +58,8 @@ const generateTrackFragmentIndexFromPath = async (absolutePath) => {
57
58
  sample_size: audioTrack.audio.sample_size,
58
59
  sample_count: audioTrack.nb_samples,
59
60
  timescale: track.timescale,
60
- duration: 0,
61
+ codec: audioTrack.codec,
62
+ duration: audioTrack.duration,
61
63
  initSegment: {
62
64
  offset: 0,
63
65
  size: fragment.data.byteLength
@@ -85,12 +87,15 @@ const generateTrackFragmentIndexFromPath = async (absolutePath) => {
85
87
  trackByteOffsets[fragment.track] += fragment.data.byteLength;
86
88
  }
87
89
  }
88
- return JSON.stringify(trackFragmentIndexes, null, 2);
90
+ return trackFragmentIndexes;
89
91
  };
90
92
  const generateTrackFragmentIndexTask = idempotentTask({
91
93
  label: "trackFragmentIndex",
92
94
  filename: (absolutePath) => `${basename(absolutePath)}.tracks.json`,
93
- runner: generateTrackFragmentIndexFromPath
95
+ runner: async (absolutePath) => {
96
+ const index = await generateTrackFragmentIndexFromPath(absolutePath);
97
+ return JSON.stringify(index, null, 2);
98
+ }
94
99
  });
95
100
  const generateTrackFragmentIndex = async (cacheRoot, absolutePath) => {
96
101
  try {
@@ -101,5 +106,6 @@ const generateTrackFragmentIndex = async (cacheRoot, absolutePath) => {
101
106
  }
102
107
  };
103
108
  export {
104
- generateTrackFragmentIndex
109
+ generateTrackFragmentIndex,
110
+ generateTrackFragmentIndexFromPath
105
111
  };