@hyperframes/engine 0.1.11 → 0.1.13
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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/videoFrameExtractor.d.ts.map +1 -1
- package/dist/services/videoFrameExtractor.js +29 -5
- package/dist/services/videoFrameExtractor.js.map +1 -1
- package/dist/utils/ffprobe.d.ts +14 -0
- package/dist/utils/ffprobe.d.ts.map +1 -1
- package/dist/utils/ffprobe.js +139 -101
- package/dist/utils/ffprobe.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +2 -0
- package/src/services/videoFrameExtractor.ts +29 -5
- package/src/utils/ffprobe.ts +157 -120
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,6 @@ export type { AudioElement, AudioTrack, MixResult } from "./services/audioMixer.
|
|
|
44
44
|
export { calculateOptimalWorkers, distributeFrames, executeParallelCapture, mergeWorkerFrames, getSystemResources, type WorkerTask, type WorkerResult, type ParallelProgress, } from "./services/parallelCoordinator.js";
|
|
45
45
|
export { createFileServer, type FileServerOptions, type FileServerHandle, } from "./services/fileServer.js";
|
|
46
46
|
export { quantizeTimeToFrame, MEDIA_VISUAL_STYLE_PROPERTIES } from "@hyperframes/core";
|
|
47
|
-
export { extractVideoMetadata, extractAudioMetadata, type VideoMetadata, type AudioMetadata, } from "./utils/ffprobe.js";
|
|
47
|
+
export { extractVideoMetadata, extractAudioMetadata, analyzeKeyframeIntervals, type VideoMetadata, type AudioMetadata, type KeyframeAnalysis, } from "./utils/ffprobe.js";
|
|
48
48
|
export { downloadToTemp, isHttpUrl } from "./utils/urlDownloader.js";
|
|
49
49
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,YAAY,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAG/E,OAAO,EACL,cAAc,EACd,cAAc,EACd,wBAAwB,EACxB,eAAe,EACf,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,6BAA6B,EAC7B,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACvB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,eAAe,EACf,KAAK,gBAAgB,GACtB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,KAAK,UAAU,GAChB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAEhG,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,GACxB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACvF,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAG1F,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACtB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACL,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAEvF,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,YAAY,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAG/E,OAAO,EACL,cAAc,EACd,cAAc,EACd,wBAAwB,EACxB,eAAe,EACf,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,6BAA6B,EAC7B,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACvB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,eAAe,EACf,KAAK,gBAAgB,GACtB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,KAAK,UAAU,GAChB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAEhG,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,GACxB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACvF,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAG1F,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACtB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACL,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAEvF,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -50,6 +50,6 @@ export { calculateOptimalWorkers, distributeFrames, executeParallelCapture, merg
|
|
|
50
50
|
export { createFileServer, } from "./services/fileServer.js";
|
|
51
51
|
// ── Utilities ──────────────────────────────────────────────────────────────────
|
|
52
52
|
export { quantizeTimeToFrame, MEDIA_VISUAL_STYLE_PROPERTIES } from "@hyperframes/core";
|
|
53
|
-
export { extractVideoMetadata, extractAudioMetadata, } from "./utils/ffprobe.js";
|
|
53
|
+
export { extractVideoMetadata, extractAudioMetadata, analyzeKeyframeIntervals, } from "./utils/ffprobe.js";
|
|
54
54
|
export { downloadToTemp, isHttpUrl } from "./utils/urlDownloader.js";
|
|
55
55
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAYH,kFAAkF;AAClF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAqB,MAAM,aAAa,CAAC;AAE/E,kFAAkF;AAClF,OAAO,EACL,cAAc,EACd,cAAc,EACd,wBAAwB,EACxB,eAAe,EACf,mBAAmB,GAIpB,MAAM,8BAA8B,CAAC;AAEtC,mFAAmF;AACnF,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,6BAA6B,GAG9B,MAAM,4BAA4B,CAAC;AAEpC,mFAAmF;AACnF,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,eAAe,GAEhB,MAAM,iCAAiC,CAAC;AAEzC,kFAAkF;AAClF,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GAEjB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,qBAAqB,EACrB,wBAAwB,GAKzB,MAAM,gCAAgC,CAAC;AAExC,kFAAkF;AAClF,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACd,sBAAsB,EACtB,gBAAgB,GAKjB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAGvF,kFAAkF;AAClF,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,GAInB,MAAM,mCAAmC,CAAC;AAE3C,kFAAkF;AAClF,OAAO,EACL,gBAAgB,GAGjB,MAAM,0BAA0B,CAAC;AAElC,kFAAkF;AAClF,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAEvF,OAAO,EACL,oBAAoB,EACpB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAYH,kFAAkF;AAClF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAqB,MAAM,aAAa,CAAC;AAE/E,kFAAkF;AAClF,OAAO,EACL,cAAc,EACd,cAAc,EACd,wBAAwB,EACxB,eAAe,EACf,mBAAmB,GAIpB,MAAM,8BAA8B,CAAC;AAEtC,mFAAmF;AACnF,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,6BAA6B,GAG9B,MAAM,4BAA4B,CAAC;AAEpC,mFAAmF;AACnF,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,eAAe,GAEhB,MAAM,iCAAiC,CAAC;AAEzC,kFAAkF;AAClF,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GAEjB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,qBAAqB,EACrB,wBAAwB,GAKzB,MAAM,gCAAgC,CAAC;AAExC,kFAAkF;AAClF,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACd,sBAAsB,EACtB,gBAAgB,GAKjB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAGvF,kFAAkF;AAClF,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,GAInB,MAAM,mCAAmC,CAAC;AAE3C,kFAAkF;AAClF,OAAO,EACL,gBAAgB,GAGjB,MAAM,0BAA0B,CAAC;AAElC,kFAAkF;AAClF,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAEvF,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,GAIzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"videoFrameExtractor.d.ts","sourceRoot":"","sources":["../../src/services/videoFrameExtractor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"videoFrameExtractor.d.ts","sourceRoot":"","sources":["../../src/services/videoFrameExtractor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAiD/D;AAED,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,iBAAiB,EAC1B,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC,GAC3D,OAAO,CAAC,eAAe,CAAC,CA0F1B;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EAAE,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,EAC1B,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC,GAC3D,OAAO,CAAC,gBAAgB,CAAC,CA8E3B;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAE,eAAe,EAC1B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAMf;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAQA;IACd,OAAO,CAAC,aAAa,CAMb;IACR,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAuB;IAEvC,QAAQ,CAAC,SAAS,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAQ1F,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO5D,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,gBAAgB;IAuCxB,sBAAsB,CACpB,UAAU,EAAE,MAAM,GACjB,GAAG,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAgBzD,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IASxD,OAAO,IAAI,IAAI;CAUhB;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,YAAY,EAAE,EACtB,SAAS,EAAE,eAAe,EAAE,GAC3B,gBAAgB,CAWlB"}
|
|
@@ -14,7 +14,16 @@ import { DEFAULT_CONFIG } from "../config.js";
|
|
|
14
14
|
export function parseVideoElements(html) {
|
|
15
15
|
const videos = [];
|
|
16
16
|
const { document } = parseHTML(html);
|
|
17
|
-
|
|
17
|
+
// Union: original "video[id][src]" (backward compat) + "video[src][data-start]"
|
|
18
|
+
// (sub-composition videos that have timing but no explicit id).
|
|
19
|
+
const videoEls = Array.from(new Set([
|
|
20
|
+
...Array.from(document.querySelectorAll("video[id][src]")),
|
|
21
|
+
...Array.from(document.querySelectorAll("video[src][data-start]")),
|
|
22
|
+
]));
|
|
23
|
+
videoEls.forEach((el, i) => {
|
|
24
|
+
if (!el.id)
|
|
25
|
+
el.id = `hf-video-${i}`;
|
|
26
|
+
});
|
|
18
27
|
for (const el of videoEls) {
|
|
19
28
|
const id = el.getAttribute("id");
|
|
20
29
|
const src = el.getAttribute("src");
|
|
@@ -22,13 +31,27 @@ export function parseVideoElements(html) {
|
|
|
22
31
|
continue;
|
|
23
32
|
const startAttr = el.getAttribute("data-start");
|
|
24
33
|
const endAttr = el.getAttribute("data-end");
|
|
34
|
+
const durationAttr = el.getAttribute("data-duration");
|
|
25
35
|
const mediaStartAttr = el.getAttribute("data-media-start");
|
|
26
36
|
const hasAudioAttr = el.getAttribute("data-has-audio");
|
|
37
|
+
const start = startAttr ? parseFloat(startAttr) : 0;
|
|
38
|
+
// Derive end from data-end → data-start+data-duration → Infinity (natural duration).
|
|
39
|
+
// The caller (htmlCompiler) clamps Infinity to the composition's absoluteEnd.
|
|
40
|
+
let end = 0;
|
|
41
|
+
if (endAttr) {
|
|
42
|
+
end = parseFloat(endAttr);
|
|
43
|
+
}
|
|
44
|
+
else if (durationAttr) {
|
|
45
|
+
end = start + parseFloat(durationAttr);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
end = Infinity; // no explicit bounds — play for the full natural video duration
|
|
49
|
+
}
|
|
27
50
|
videos.push({
|
|
28
51
|
id,
|
|
29
52
|
src,
|
|
30
|
-
start
|
|
31
|
-
end
|
|
53
|
+
start,
|
|
54
|
+
end,
|
|
32
55
|
mediaStart: mediaStartAttr ? parseFloat(mediaStartAttr) : 0,
|
|
33
56
|
hasAudio: hasAudioAttr === "true",
|
|
34
57
|
});
|
|
@@ -146,8 +169,9 @@ export async function extractAllVideoFrames(videos, baseDir, options, signal, co
|
|
|
146
169
|
return { error: { videoId: video.id, error: `Video file not found: ${videoPath}` } };
|
|
147
170
|
}
|
|
148
171
|
let videoDuration = video.end - video.start;
|
|
149
|
-
// Fallback: if no data-duration/data-end was specified
|
|
150
|
-
|
|
172
|
+
// Fallback: if no data-duration/data-end was specified (end is Infinity or 0),
|
|
173
|
+
// probe the actual video file to get its natural duration.
|
|
174
|
+
if (!Number.isFinite(videoDuration) || videoDuration <= 0) {
|
|
151
175
|
const metadata = await extractVideoMetadata(videoPath);
|
|
152
176
|
const sourceDuration = metadata.durationSeconds - video.mediaStart;
|
|
153
177
|
videoDuration = sourceDuration > 0 ? sourceDuration : metadata.durationSeconds;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"videoFrameExtractor.js","sourceRoot":"","sources":["../../src/services/videoFrameExtractor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAsB,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,cAAc,EAAqB,MAAM,cAAc,CAAC;AAqCjE,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAErC,MAAM,QAAQ,GAAG,QAAQ,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAC7D,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG;YAAE,SAAS;QAE1B,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,cAAc,GAAG,EAAE,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;QAC3D,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QAEvD,MAAM,CAAC,IAAI,CAAC;YACV,EAAE;YACF,GAAG;YACH,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3D,QAAQ,EAAE,YAAY,KAAK,MAAM;SAClC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,SAAiB,EACjB,OAAe,EACf,SAAiB,EACjB,QAAgB,EAChB,OAA0B,EAC1B,MAAoB,EACpB,MAA4D;IAE5D,MAAM,oBAAoB,GAAG,MAAM,EAAE,oBAAoB,IAAI,cAAc,CAAC,oBAAoB,CAAC;IACjG,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,GAAG,EAAE,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAEjE,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAChD,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC;QAAE,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhF,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,cAAc,MAAM,EAAE,CAAC;IAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;IAEzD,MAAM,IAAI,GAAa;QACrB,KAAK;QACL,MAAM,CAAC,SAAS,CAAC;QACjB,IAAI;QACJ,SAAS;QACT,IAAI;QACJ,MAAM,CAAC,QAAQ,CAAC;QAChB,KAAK;QACL,OAAO,GAAG,EAAE;QACZ,MAAM;QACN,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;KAChE,CAAC;IACF,IAAI,MAAM,KAAK,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;IAC3D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAE/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrC,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC,CAAC;QACF,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAEzB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,MAAM;gBAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACzD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,MAAM,CAAC,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC;YACD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC5E,OAAO;YACT,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC7C,MAAM,KAAK,GAAG,WAAW,CAAC,cAAc,CAAC;iBACtC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC;iBACjE,IAAI,EAAE,CAAC;YACV,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC5B,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;YAEH,OAAO,CAAC;gBACN,OAAO;gBACP,OAAO,EAAE,SAAS;gBAClB,SAAS,EAAE,cAAc;gBACzB,YAAY;gBACZ,GAAG;gBACH,WAAW,EAAE,UAAU,CAAC,IAAI;gBAC5B,QAAQ;gBACR,UAAU;aACX,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,MAAM;gBAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACzD,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACjD,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAsB,EACtB,OAAe,EACf,OAA0B,EAC1B,MAAoB,EACpB,MAA4D;IAE5D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,MAAM,MAAM,GAA8C,EAAE,CAAC;IAC7D,IAAI,oBAAoB,GAAG,CAAC,CAAC;IAE7B,oDAAoD;IACpD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACzB,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC;YACH,IAAI,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC;YAC1B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxD,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;gBACzB,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;gBAC1D,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC5C,SAAS,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YAC3D,CAAC;YAED,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3B,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,yBAAyB,SAAS,EAAE,EAAE,EAAE,CAAC;YACvF,CAAC;YAED,IAAI,aAAa,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;YAE5C,8EAA8E;YAC9E,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;gBACvB,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAC;gBACvD,MAAM,cAAc,GAAG,QAAQ,CAAC,eAAe,GAAG,KAAK,CAAC,UAAU,CAAC;gBACnE,aAAa,GAAG,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC;gBAC/E,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,aAAa,CAAC;YAC1C,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAC1C,SAAS,EACT,KAAK,CAAC,EAAE,EACR,KAAK,CAAC,UAAU,EAChB,aAAa,EACb,OAAO,EACP,MAAM,EACN,MAAM,CACP,CAAC;YAEF,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,KAAK,EAAE;oBACL,OAAO,EAAE,KAAK,CAAC,EAAE;oBACjB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACxD;aACF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CACH,CAAC;IAEF,6BAA6B;IAC7B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YAC5B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5B,oBAAoB,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QAClD,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC5B,SAAS;QACT,MAAM;QACN,oBAAoB;QACpB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;KACnC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,SAA0B,EAC1B,UAAkB,EAClB,UAAkB;IAElB,MAAM,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC1C,IAAI,SAAS,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IACzD,IAAI,UAAU,GAAG,CAAC,IAAI,UAAU,IAAI,SAAS,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IACvE,OAAO,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;AACtD,CAAC;AAED,MAAM,OAAO,gBAAgB;IACnB,MAAM,GAQV,IAAI,GAAG,EAAE,CAAC;IACN,aAAa,GAMhB,EAAE,CAAC;IACA,cAAc,GAAgB,IAAI,GAAG,EAAE,CAAC;IACxC,WAAW,GAAG,CAAC,CAAC;IAChB,QAAQ,GAAkB,IAAI,CAAC;IAEvC,QAAQ,CAAC,SAA0B,EAAE,KAAa,EAAE,GAAW,EAAE,UAAkB;QACjF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;aACnD,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;aAClD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAED,QAAQ,CAAC,OAAe,EAAE,UAAkB;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,UAAU,GAAG,KAAK,CAAC,KAAK,IAAI,UAAU,IAAI,KAAK,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACrE,OAAO,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAClE,CAAC;IAEO,gBAAgB;QACtB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvB,CAAC;IAEO,gBAAgB,CAAC,UAAkB;QACzC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,IAAI,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YACrB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvC,IAAI,KAAK,CAAC,KAAK,IAAI,UAAU,IAAI,UAAU,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;oBACxD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACzC,CAAC;gBACD,IAAI,KAAK,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC;oBAC9B,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YACpD,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACvD,IAAI,CAAC,SAAS;gBAAE,MAAM;YACtB,IAAI,SAAS,CAAC,KAAK,GAAG,UAAU,EAAE,CAAC;gBACjC,MAAM;YACR,CAAC;YACD,IAAI,UAAU,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC;gBAC/B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAC7C,CAAC;YACD,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;QACxB,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,IAAI,UAAU,GAAG,KAAK,CAAC,KAAK,IAAI,UAAU,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;gBAClE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC;IAC7B,CAAC;IAED,sBAAsB,CACpB,UAAkB;QAElB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqD,CAAC;QAC5E,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAClC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,MAAM,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;YAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC/D,IAAI,UAAU,GAAG,CAAC,IAAI,UAAU,IAAI,KAAK,CAAC,SAAS,CAAC,WAAW;gBAAE,SAAS;YAC1E,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC7D,IAAI,CAAC,SAAS;gBAAE,SAAS;YACzB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,eAAe,CAAC,UAAkB;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO;QACL,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,IAAI,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1C,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CACpC,MAAsB,EACtB,SAA4B;IAE5B,MAAM,KAAK,GAAG,IAAI,gBAAgB,EAAE,CAAC;IACrC,MAAM,YAAY,GAAG,IAAI,GAAG,EAA2B,CAAC;IACxD,KAAK,MAAM,GAAG,IAAI,SAAS;QAAE,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAEhE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvC,IAAI,GAAG;YAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
1
|
+
{"version":3,"file":"videoFrameExtractor.js","sourceRoot":"","sources":["../../src/services/videoFrameExtractor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAsB,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,cAAc,EAAqB,MAAM,cAAc,CAAC;AAqCjE,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAErC,gFAAgF;IAChF,gEAAgE;IAChE,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CACzB,IAAI,GAAG,CAAC;QACN,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;QAC1D,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,CAAC;KACnE,CAAC,CACH,CAAC;IACF,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;QACzB,IAAI,CAAC,EAAE,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,GAAG,YAAY,CAAC,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IACH,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG;YAAE,SAAS;QAE1B,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;QACtD,MAAM,cAAc,GAAG,EAAE,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;QAC3D,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QAEvD,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,qFAAqF;QACrF,8EAA8E;QAC9E,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,YAAY,EAAE,CAAC;YACxB,GAAG,GAAG,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,QAAQ,CAAC,CAAC,gEAAgE;QAClF,CAAC;QAED,MAAM,CAAC,IAAI,CAAC;YACV,EAAE;YACF,GAAG;YACH,KAAK;YACL,GAAG;YACH,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3D,QAAQ,EAAE,YAAY,KAAK,MAAM;SAClC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,SAAiB,EACjB,OAAe,EACf,SAAiB,EACjB,QAAgB,EAChB,OAA0B,EAC1B,MAAoB,EACpB,MAA4D;IAE5D,MAAM,oBAAoB,GAAG,MAAM,EAAE,oBAAoB,IAAI,cAAc,CAAC,oBAAoB,CAAC;IACjG,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,GAAG,EAAE,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAEjE,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAChD,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC;QAAE,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhF,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,cAAc,MAAM,EAAE,CAAC;IAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;IAEzD,MAAM,IAAI,GAAa;QACrB,KAAK;QACL,MAAM,CAAC,SAAS,CAAC;QACjB,IAAI;QACJ,SAAS;QACT,IAAI;QACJ,MAAM,CAAC,QAAQ,CAAC;QAChB,KAAK;QACL,OAAO,GAAG,EAAE;QACZ,MAAM;QACN,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;KAChE,CAAC;IACF,IAAI,MAAM,KAAK,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;IAC3D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAE/B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrC,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC,CAAC;QACF,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAEzB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YAChC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAC1B,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,MAAM;gBAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACzD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,MAAM,CAAC,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC;YACD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC5E,OAAO;YACT,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC7C,MAAM,KAAK,GAAG,WAAW,CAAC,cAAc,CAAC;iBACtC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC;iBACjE,IAAI,EAAE,CAAC;YACV,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC5B,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;YAEH,OAAO,CAAC;gBACN,OAAO;gBACP,OAAO,EAAE,SAAS;gBAClB,SAAS,EAAE,cAAc;gBACzB,YAAY;gBACZ,GAAG;gBACH,WAAW,EAAE,UAAU,CAAC,IAAI;gBAC5B,QAAQ;gBACR,UAAU;aACX,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,MAAM;gBAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACzD,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACjD,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAsB,EACtB,OAAe,EACf,OAA0B,EAC1B,MAAoB,EACpB,MAA4D;IAE5D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,MAAM,MAAM,GAA8C,EAAE,CAAC;IAC7D,IAAI,oBAAoB,GAAG,CAAC,CAAC;IAE7B,oDAAoD;IACpD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACzB,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC;YACH,IAAI,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC;YAC1B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;gBACxD,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;gBACzB,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;gBAC1D,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC5C,SAAS,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YAC3D,CAAC;YAED,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC3B,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,yBAAyB,SAAS,EAAE,EAAE,EAAE,CAAC;YACvF,CAAC;YAED,IAAI,aAAa,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;YAE5C,+EAA+E;YAC/E,2DAA2D;YAC3D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;gBAC1D,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAC;gBACvD,MAAM,cAAc,GAAG,QAAQ,CAAC,eAAe,GAAG,KAAK,CAAC,UAAU,CAAC;gBACnE,aAAa,GAAG,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC;gBAC/E,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,aAAa,CAAC;YAC1C,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAC1C,SAAS,EACT,KAAK,CAAC,EAAE,EACR,KAAK,CAAC,UAAU,EAChB,aAAa,EACb,OAAO,EACP,MAAM,EACN,MAAM,CACP,CAAC;YAEF,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,KAAK,EAAE;oBACL,OAAO,EAAE,KAAK,CAAC,EAAE;oBACjB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACxD;aACF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CACH,CAAC;IAEF,6BAA6B;IAC7B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YAC5B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5B,oBAAoB,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QAClD,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC5B,SAAS;QACT,MAAM;QACN,oBAAoB;QACpB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;KACnC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,SAA0B,EAC1B,UAAkB,EAClB,UAAkB;IAElB,MAAM,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC1C,IAAI,SAAS,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IACzD,IAAI,UAAU,GAAG,CAAC,IAAI,UAAU,IAAI,SAAS,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IACvE,OAAO,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;AACtD,CAAC;AAED,MAAM,OAAO,gBAAgB;IACnB,MAAM,GAQV,IAAI,GAAG,EAAE,CAAC;IACN,aAAa,GAMhB,EAAE,CAAC;IACA,cAAc,GAAgB,IAAI,GAAG,EAAE,CAAC;IACxC,WAAW,GAAG,CAAC,CAAC;IAChB,QAAQ,GAAkB,IAAI,CAAC;IAEvC,QAAQ,CAAC,SAA0B,EAAE,KAAa,EAAE,GAAW,EAAE,UAAkB;QACjF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;aACnD,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;aAClD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAED,QAAQ,CAAC,OAAe,EAAE,UAAkB;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,UAAU,GAAG,KAAK,CAAC,KAAK,IAAI,UAAU,IAAI,KAAK,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACrE,OAAO,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAClE,CAAC;IAEO,gBAAgB;QACtB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvB,CAAC;IAEO,gBAAgB,CAAC,UAAkB;QACzC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,IAAI,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YACrB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvC,IAAI,KAAK,CAAC,KAAK,IAAI,UAAU,IAAI,UAAU,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;oBACxD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACzC,CAAC;gBACD,IAAI,KAAK,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC;oBAC9B,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;gBACxB,CAAC;qBAAM,CAAC;oBACN,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,OAAO,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;YACpD,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACvD,IAAI,CAAC,SAAS;gBAAE,MAAM;YACtB,IAAI,SAAS,CAAC,KAAK,GAAG,UAAU,EAAE,CAAC;gBACjC,MAAM;YACR,CAAC;YACD,IAAI,UAAU,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC;gBAC/B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAC7C,CAAC;YACD,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;QACxB,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,IAAI,UAAU,GAAG,KAAK,CAAC,KAAK,IAAI,UAAU,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;gBAClE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC;IAC7B,CAAC;IAED,sBAAsB,CACpB,UAAkB;QAElB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqD,CAAC;QAC5E,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAClC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,MAAM,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;YAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAC/D,IAAI,UAAU,GAAG,CAAC,IAAI,UAAU,IAAI,KAAK,CAAC,SAAS,CAAC,WAAW;gBAAE,SAAS;YAC1E,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC7D,IAAI,CAAC,SAAS;gBAAE,SAAS;YACzB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,eAAe,CAAC,UAAkB;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO;QACL,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,IAAI,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1C,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CACpC,MAAsB,EACtB,SAA4B;IAE5B,MAAM,KAAK,GAAG,IAAI,gBAAgB,EAAE,CAAC;IACrC,MAAM,YAAY,GAAG,IAAI,GAAG,EAA2B,CAAC;IACxD,KAAK,MAAM,GAAG,IAAI,SAAS;QAAE,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAEhE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvC,IAAI,GAAG;YAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/utils/ffprobe.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export interface VideoMetadata {
|
|
|
5
5
|
fps: number;
|
|
6
6
|
videoCodec: string;
|
|
7
7
|
hasAudio: boolean;
|
|
8
|
+
/** True when r_frame_rate and avg_frame_rate differ significantly (>10%), indicating variable frame rate. */
|
|
9
|
+
isVFR: boolean;
|
|
8
10
|
}
|
|
9
11
|
export interface AudioMetadata {
|
|
10
12
|
durationSeconds: number;
|
|
@@ -15,4 +17,16 @@ export interface AudioMetadata {
|
|
|
15
17
|
}
|
|
16
18
|
export declare function extractVideoMetadata(filePath: string): Promise<VideoMetadata>;
|
|
17
19
|
export declare function extractAudioMetadata(filePath: string): Promise<AudioMetadata>;
|
|
20
|
+
export interface KeyframeAnalysis {
|
|
21
|
+
avgIntervalSeconds: number;
|
|
22
|
+
maxIntervalSeconds: number;
|
|
23
|
+
keyframeCount: number;
|
|
24
|
+
isProblematic: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Check keyframe intervals in a video file. Intervals > 2s cause seeking
|
|
28
|
+
* issues in the headless renderer and audio/video desync. Videos from
|
|
29
|
+
* yt-dlp --download-sections or screen recordings often have sparse keyframes.
|
|
30
|
+
*/
|
|
31
|
+
export declare function analyzeKeyframeIntervals(filePath: string): Promise<KeyframeAnalysis>;
|
|
18
32
|
//# sourceMappingURL=ffprobe.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ffprobe.d.ts","sourceRoot":"","sources":["../../src/utils/ffprobe.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ffprobe.d.ts","sourceRoot":"","sources":["../../src/utils/ffprobe.ts"],"names":[],"mappings":"AA4CA,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,6GAA6G;IAC7G,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAkCD,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA0CnF;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAoCnF;AAED,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;CACxB;AAID;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAY1F"}
|
package/dist/utils/ffprobe.js
CHANGED
|
@@ -1,4 +1,42 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
|
+
/** Spawn ffprobe with given args, return stdout. Throws on non-zero exit or missing binary. */
|
|
3
|
+
function runFfprobe(args) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const proc = spawn("ffprobe", args);
|
|
6
|
+
let stdout = "";
|
|
7
|
+
let stderr = "";
|
|
8
|
+
proc.stdout.on("data", (data) => {
|
|
9
|
+
stdout += data.toString();
|
|
10
|
+
});
|
|
11
|
+
proc.stderr.on("data", (data) => {
|
|
12
|
+
stderr += data.toString();
|
|
13
|
+
});
|
|
14
|
+
proc.on("close", (code) => {
|
|
15
|
+
if (code !== 0) {
|
|
16
|
+
reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
resolve(stdout);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
proc.on("error", (err) => {
|
|
23
|
+
if (err.code === "ENOENT") {
|
|
24
|
+
reject(new Error("[FFmpeg] ffprobe not found. Please install FFmpeg."));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
reject(err);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function parseProbeJson(stdout) {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(stdout);
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
throw new Error(`[FFmpeg] Failed to parse ffprobe output: ${e instanceof Error ? e.message : e}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
2
40
|
const videoMetadataCache = new Map();
|
|
3
41
|
const audioMetadataCache = new Map();
|
|
4
42
|
function parseFrameRate(frameRateStr) {
|
|
@@ -15,11 +53,10 @@ function parseFrameRate(frameRateStr) {
|
|
|
15
53
|
}
|
|
16
54
|
export async function extractVideoMetadata(filePath) {
|
|
17
55
|
const cached = videoMetadataCache.get(filePath);
|
|
18
|
-
if (cached)
|
|
56
|
+
if (cached)
|
|
19
57
|
return cached;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const args = [
|
|
58
|
+
const probePromise = (async () => {
|
|
59
|
+
const stdout = await runFfprobe([
|
|
23
60
|
"-v",
|
|
24
61
|
"quiet",
|
|
25
62
|
"-print_format",
|
|
@@ -27,54 +64,26 @@ export async function extractVideoMetadata(filePath) {
|
|
|
27
64
|
"-show_format",
|
|
28
65
|
"-show_streams",
|
|
29
66
|
filePath,
|
|
30
|
-
];
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
const hasAudio = output.streams.some((s) => s.codec_type === "audio");
|
|
53
|
-
const fps = parseFrameRate(videoStream.avg_frame_rate) || parseFrameRate(videoStream.r_frame_rate);
|
|
54
|
-
const durationSeconds = output.format.duration ? parseFloat(output.format.duration) : 0;
|
|
55
|
-
const metadata = {
|
|
56
|
-
durationSeconds,
|
|
57
|
-
width: videoStream.width || 0,
|
|
58
|
-
height: videoStream.height || 0,
|
|
59
|
-
fps,
|
|
60
|
-
videoCodec: videoStream.codec_name || "unknown",
|
|
61
|
-
hasAudio,
|
|
62
|
-
};
|
|
63
|
-
resolve(metadata);
|
|
64
|
-
}
|
|
65
|
-
catch (parseError) {
|
|
66
|
-
reject(new Error(`[FFmpeg] Failed to parse ffprobe output: ${parseError instanceof Error ? parseError.message : parseError}`));
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
ffprobe.on("error", (err) => {
|
|
70
|
-
if (err.code === "ENOENT") {
|
|
71
|
-
reject(new Error("[FFmpeg] ffprobe not found. Please install FFmpeg."));
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
reject(err);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
});
|
|
67
|
+
]);
|
|
68
|
+
const output = parseProbeJson(stdout);
|
|
69
|
+
const videoStream = output.streams.find((s) => s.codec_type === "video");
|
|
70
|
+
if (!videoStream)
|
|
71
|
+
throw new Error("[FFmpeg] No video stream found");
|
|
72
|
+
const rFps = parseFrameRate(videoStream.r_frame_rate);
|
|
73
|
+
const avgFps = parseFrameRate(videoStream.avg_frame_rate);
|
|
74
|
+
const fps = avgFps || rFps;
|
|
75
|
+
// VFR: r_frame_rate (max/nominal) differs from avg_frame_rate (actual average) by >10%
|
|
76
|
+
const isVFR = rFps > 0 && avgFps > 0 && Math.abs(rFps - avgFps) / Math.max(rFps, avgFps) > 0.1;
|
|
77
|
+
return {
|
|
78
|
+
durationSeconds: output.format.duration ? parseFloat(output.format.duration) : 0,
|
|
79
|
+
width: videoStream.width || 0,
|
|
80
|
+
height: videoStream.height || 0,
|
|
81
|
+
fps,
|
|
82
|
+
videoCodec: videoStream.codec_name || "unknown",
|
|
83
|
+
hasAudio: output.streams.some((s) => s.codec_type === "audio"),
|
|
84
|
+
isVFR,
|
|
85
|
+
};
|
|
86
|
+
})();
|
|
78
87
|
videoMetadataCache.set(filePath, probePromise);
|
|
79
88
|
probePromise.catch(() => {
|
|
80
89
|
if (videoMetadataCache.get(filePath) === probePromise) {
|
|
@@ -85,11 +94,10 @@ export async function extractVideoMetadata(filePath) {
|
|
|
85
94
|
}
|
|
86
95
|
export async function extractAudioMetadata(filePath) {
|
|
87
96
|
const cached = audioMetadataCache.get(filePath);
|
|
88
|
-
if (cached)
|
|
97
|
+
if (cached)
|
|
89
98
|
return cached;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const args = [
|
|
99
|
+
const probePromise = (async () => {
|
|
100
|
+
const stdout = await runFfprobe([
|
|
93
101
|
"-v",
|
|
94
102
|
"quiet",
|
|
95
103
|
"-print_format",
|
|
@@ -97,51 +105,20 @@ export async function extractAudioMetadata(filePath) {
|
|
|
97
105
|
"-show_format",
|
|
98
106
|
"-show_streams",
|
|
99
107
|
filePath,
|
|
100
|
-
];
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
try {
|
|
116
|
-
const output = JSON.parse(stdout);
|
|
117
|
-
const audioStream = output.streams.find((s) => s.codec_type === "audio");
|
|
118
|
-
if (!audioStream) {
|
|
119
|
-
reject(new Error("[FFmpeg] No audio stream found"));
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
const durationSeconds = output.format.duration ? parseFloat(output.format.duration) : 0;
|
|
123
|
-
const metadata = {
|
|
124
|
-
durationSeconds,
|
|
125
|
-
sampleRate: audioStream.sample_rate ? parseInt(audioStream.sample_rate) : 44100,
|
|
126
|
-
channels: audioStream.channels || 2,
|
|
127
|
-
audioCodec: audioStream.codec_name || "unknown",
|
|
128
|
-
bitrate: output.format.bit_rate ? parseInt(output.format.bit_rate) : undefined,
|
|
129
|
-
};
|
|
130
|
-
resolve(metadata);
|
|
131
|
-
}
|
|
132
|
-
catch (parseError) {
|
|
133
|
-
reject(new Error(`[FFmpeg] Failed to parse ffprobe output: ${parseError instanceof Error ? parseError.message : parseError}`));
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
ffprobe.on("error", (err) => {
|
|
137
|
-
if (err.code === "ENOENT") {
|
|
138
|
-
reject(new Error("[FFmpeg] ffprobe not found. Please install FFmpeg."));
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
reject(err);
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
});
|
|
108
|
+
]);
|
|
109
|
+
const output = parseProbeJson(stdout);
|
|
110
|
+
const audioStream = output.streams.find((s) => s.codec_type === "audio");
|
|
111
|
+
if (!audioStream)
|
|
112
|
+
throw new Error("[FFmpeg] No audio stream found");
|
|
113
|
+
const durationSeconds = output.format.duration ? parseFloat(output.format.duration) : 0;
|
|
114
|
+
return {
|
|
115
|
+
durationSeconds,
|
|
116
|
+
sampleRate: audioStream.sample_rate ? parseInt(audioStream.sample_rate) : 44100,
|
|
117
|
+
channels: audioStream.channels || 2,
|
|
118
|
+
audioCodec: audioStream.codec_name || "unknown",
|
|
119
|
+
bitrate: output.format.bit_rate ? parseInt(output.format.bit_rate) : undefined,
|
|
120
|
+
};
|
|
121
|
+
})();
|
|
145
122
|
audioMetadataCache.set(filePath, probePromise);
|
|
146
123
|
probePromise.catch(() => {
|
|
147
124
|
if (audioMetadataCache.get(filePath) === probePromise) {
|
|
@@ -150,4 +127,65 @@ export async function extractAudioMetadata(filePath) {
|
|
|
150
127
|
});
|
|
151
128
|
return probePromise;
|
|
152
129
|
}
|
|
130
|
+
const keyframeCache = new Map();
|
|
131
|
+
/**
|
|
132
|
+
* Check keyframe intervals in a video file. Intervals > 2s cause seeking
|
|
133
|
+
* issues in the headless renderer and audio/video desync. Videos from
|
|
134
|
+
* yt-dlp --download-sections or screen recordings often have sparse keyframes.
|
|
135
|
+
*/
|
|
136
|
+
export async function analyzeKeyframeIntervals(filePath) {
|
|
137
|
+
const cached = keyframeCache.get(filePath);
|
|
138
|
+
if (cached)
|
|
139
|
+
return cached;
|
|
140
|
+
const promise = analyzeKeyframeIntervalsUncached(filePath);
|
|
141
|
+
keyframeCache.set(filePath, promise);
|
|
142
|
+
promise.catch(() => {
|
|
143
|
+
if (keyframeCache.get(filePath) === promise) {
|
|
144
|
+
keyframeCache.delete(filePath);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
return promise;
|
|
148
|
+
}
|
|
149
|
+
async function analyzeKeyframeIntervalsUncached(filePath) {
|
|
150
|
+
const stdout = await runFfprobe([
|
|
151
|
+
"-v",
|
|
152
|
+
"quiet",
|
|
153
|
+
"-select_streams",
|
|
154
|
+
"v:0",
|
|
155
|
+
"-skip_frame",
|
|
156
|
+
"nokey",
|
|
157
|
+
"-show_entries",
|
|
158
|
+
"frame=pts_time",
|
|
159
|
+
"-of",
|
|
160
|
+
"csv=p=0",
|
|
161
|
+
filePath,
|
|
162
|
+
]);
|
|
163
|
+
const timestamps = stdout
|
|
164
|
+
.split("\n")
|
|
165
|
+
.map((line) => parseFloat(line.trim()))
|
|
166
|
+
.filter((t) => Number.isFinite(t));
|
|
167
|
+
if (timestamps.length < 2) {
|
|
168
|
+
return {
|
|
169
|
+
avgIntervalSeconds: 0,
|
|
170
|
+
maxIntervalSeconds: 0,
|
|
171
|
+
keyframeCount: timestamps.length,
|
|
172
|
+
isProblematic: false,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
let maxInterval = 0;
|
|
176
|
+
let totalInterval = 0;
|
|
177
|
+
for (let i = 1; i < timestamps.length; i++) {
|
|
178
|
+
const interval = (timestamps[i] ?? 0) - (timestamps[i - 1] ?? 0);
|
|
179
|
+
totalInterval += interval;
|
|
180
|
+
if (interval > maxInterval)
|
|
181
|
+
maxInterval = interval;
|
|
182
|
+
}
|
|
183
|
+
const avgInterval = totalInterval / (timestamps.length - 1);
|
|
184
|
+
return {
|
|
185
|
+
avgIntervalSeconds: Math.round(avgInterval * 100) / 100,
|
|
186
|
+
maxIntervalSeconds: Math.round(maxInterval * 100) / 100,
|
|
187
|
+
keyframeCount: timestamps.length,
|
|
188
|
+
isProblematic: maxInterval > 2,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
153
191
|
//# sourceMappingURL=ffprobe.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ffprobe.js","sourceRoot":"","sources":["../../src/utils/ffprobe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,
|
|
1
|
+
{"version":3,"file":"ffprobe.js","sourceRoot":"","sources":["../../src/utils/ffprobe.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/engine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Seekable web page to video rendering engine (Puppeteer + FFmpeg)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"linkedom": "^0.18.12",
|
|
20
20
|
"puppeteer": "^24.0.0",
|
|
21
21
|
"puppeteer-core": "^24.39.1",
|
|
22
|
-
"@hyperframes/core": "^0.1.
|
|
22
|
+
"@hyperframes/core": "^0.1.13"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/node": "^22.10.1",
|
package/src/index.ts
CHANGED
|
@@ -146,8 +146,10 @@ export { quantizeTimeToFrame, MEDIA_VISUAL_STYLE_PROPERTIES } from "@hyperframes
|
|
|
146
146
|
export {
|
|
147
147
|
extractVideoMetadata,
|
|
148
148
|
extractAudioMetadata,
|
|
149
|
+
analyzeKeyframeIntervals,
|
|
149
150
|
type VideoMetadata,
|
|
150
151
|
type AudioMetadata,
|
|
152
|
+
type KeyframeAnalysis,
|
|
151
153
|
} from "./utils/ffprobe.js";
|
|
152
154
|
|
|
153
155
|
export { downloadToTemp, isHttpUrl } from "./utils/urlDownloader.js";
|
|
@@ -52,7 +52,17 @@ export function parseVideoElements(html: string): VideoElement[] {
|
|
|
52
52
|
const videos: VideoElement[] = [];
|
|
53
53
|
const { document } = parseHTML(html);
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
// Union: original "video[id][src]" (backward compat) + "video[src][data-start]"
|
|
56
|
+
// (sub-composition videos that have timing but no explicit id).
|
|
57
|
+
const videoEls = Array.from(
|
|
58
|
+
new Set([
|
|
59
|
+
...Array.from(document.querySelectorAll("video[id][src]")),
|
|
60
|
+
...Array.from(document.querySelectorAll("video[src][data-start]")),
|
|
61
|
+
]),
|
|
62
|
+
);
|
|
63
|
+
videoEls.forEach((el, i) => {
|
|
64
|
+
if (!el.id) el.id = `hf-video-${i}`;
|
|
65
|
+
});
|
|
56
66
|
for (const el of videoEls) {
|
|
57
67
|
const id = el.getAttribute("id");
|
|
58
68
|
const src = el.getAttribute("src");
|
|
@@ -60,14 +70,27 @@ export function parseVideoElements(html: string): VideoElement[] {
|
|
|
60
70
|
|
|
61
71
|
const startAttr = el.getAttribute("data-start");
|
|
62
72
|
const endAttr = el.getAttribute("data-end");
|
|
73
|
+
const durationAttr = el.getAttribute("data-duration");
|
|
63
74
|
const mediaStartAttr = el.getAttribute("data-media-start");
|
|
64
75
|
const hasAudioAttr = el.getAttribute("data-has-audio");
|
|
65
76
|
|
|
77
|
+
const start = startAttr ? parseFloat(startAttr) : 0;
|
|
78
|
+
// Derive end from data-end → data-start+data-duration → Infinity (natural duration).
|
|
79
|
+
// The caller (htmlCompiler) clamps Infinity to the composition's absoluteEnd.
|
|
80
|
+
let end = 0;
|
|
81
|
+
if (endAttr) {
|
|
82
|
+
end = parseFloat(endAttr);
|
|
83
|
+
} else if (durationAttr) {
|
|
84
|
+
end = start + parseFloat(durationAttr);
|
|
85
|
+
} else {
|
|
86
|
+
end = Infinity; // no explicit bounds — play for the full natural video duration
|
|
87
|
+
}
|
|
88
|
+
|
|
66
89
|
videos.push({
|
|
67
90
|
id,
|
|
68
91
|
src,
|
|
69
|
-
start
|
|
70
|
-
end
|
|
92
|
+
start,
|
|
93
|
+
end,
|
|
71
94
|
mediaStart: mediaStartAttr ? parseFloat(mediaStartAttr) : 0,
|
|
72
95
|
hasAudio: hasAudioAttr === "true",
|
|
73
96
|
});
|
|
@@ -212,8 +235,9 @@ export async function extractAllVideoFrames(
|
|
|
212
235
|
|
|
213
236
|
let videoDuration = video.end - video.start;
|
|
214
237
|
|
|
215
|
-
// Fallback: if no data-duration/data-end was specified
|
|
216
|
-
|
|
238
|
+
// Fallback: if no data-duration/data-end was specified (end is Infinity or 0),
|
|
239
|
+
// probe the actual video file to get its natural duration.
|
|
240
|
+
if (!Number.isFinite(videoDuration) || videoDuration <= 0) {
|
|
217
241
|
const metadata = await extractVideoMetadata(videoPath);
|
|
218
242
|
const sourceDuration = metadata.durationSeconds - video.mediaStart;
|
|
219
243
|
videoDuration = sourceDuration > 0 ? sourceDuration : metadata.durationSeconds;
|
package/src/utils/ffprobe.ts
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
|
|
3
|
+
/** Spawn ffprobe with given args, return stdout. Throws on non-zero exit or missing binary. */
|
|
4
|
+
function runFfprobe(args: string[]): Promise<string> {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
const proc = spawn("ffprobe", args);
|
|
7
|
+
let stdout = "";
|
|
8
|
+
let stderr = "";
|
|
9
|
+
proc.stdout.on("data", (data) => {
|
|
10
|
+
stdout += data.toString();
|
|
11
|
+
});
|
|
12
|
+
proc.stderr.on("data", (data) => {
|
|
13
|
+
stderr += data.toString();
|
|
14
|
+
});
|
|
15
|
+
proc.on("close", (code) => {
|
|
16
|
+
if (code !== 0) {
|
|
17
|
+
reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
|
|
18
|
+
} else {
|
|
19
|
+
resolve(stdout);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
proc.on("error", (err) => {
|
|
23
|
+
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
24
|
+
reject(new Error("[FFmpeg] ffprobe not found. Please install FFmpeg."));
|
|
25
|
+
} else {
|
|
26
|
+
reject(err);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function parseProbeJson(stdout: string): FFProbeOutput {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(stdout);
|
|
35
|
+
} catch (e) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`[FFmpeg] Failed to parse ffprobe output: ${e instanceof Error ? e.message : e}`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
3
42
|
const videoMetadataCache = new Map<string, Promise<VideoMetadata>>();
|
|
4
43
|
const audioMetadataCache = new Map<string, Promise<AudioMetadata>>();
|
|
5
44
|
|
|
@@ -10,6 +49,8 @@ export interface VideoMetadata {
|
|
|
10
49
|
fps: number;
|
|
11
50
|
videoCodec: string;
|
|
12
51
|
hasAudio: boolean;
|
|
52
|
+
/** True when r_frame_rate and avg_frame_rate differ significantly (>10%), indicating variable frame rate. */
|
|
53
|
+
isVFR: boolean;
|
|
13
54
|
}
|
|
14
55
|
|
|
15
56
|
export interface AudioMetadata {
|
|
@@ -54,12 +95,10 @@ function parseFrameRate(frameRateStr: string | undefined): number {
|
|
|
54
95
|
|
|
55
96
|
export async function extractVideoMetadata(filePath: string): Promise<VideoMetadata> {
|
|
56
97
|
const cached = videoMetadataCache.get(filePath);
|
|
57
|
-
if (cached)
|
|
58
|
-
return cached;
|
|
59
|
-
}
|
|
98
|
+
if (cached) return cached;
|
|
60
99
|
|
|
61
|
-
const probePromise =
|
|
62
|
-
const
|
|
100
|
+
const probePromise = (async (): Promise<VideoMetadata> => {
|
|
101
|
+
const stdout = await runFfprobe([
|
|
63
102
|
"-v",
|
|
64
103
|
"quiet",
|
|
65
104
|
"-print_format",
|
|
@@ -67,64 +106,28 @@ export async function extractVideoMetadata(filePath: string): Promise<VideoMetad
|
|
|
67
106
|
"-show_format",
|
|
68
107
|
"-show_streams",
|
|
69
108
|
filePath,
|
|
70
|
-
];
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
109
|
+
]);
|
|
110
|
+
const output = parseProbeJson(stdout);
|
|
111
|
+
const videoStream = output.streams.find((s) => s.codec_type === "video");
|
|
112
|
+
if (!videoStream) throw new Error("[FFmpeg] No video stream found");
|
|
113
|
+
|
|
114
|
+
const rFps = parseFrameRate(videoStream.r_frame_rate);
|
|
115
|
+
const avgFps = parseFrameRate(videoStream.avg_frame_rate);
|
|
116
|
+
const fps = avgFps || rFps;
|
|
117
|
+
// VFR: r_frame_rate (max/nominal) differs from avg_frame_rate (actual average) by >10%
|
|
118
|
+
const isVFR = rFps > 0 && avgFps > 0 && Math.abs(rFps - avgFps) / Math.max(rFps, avgFps) > 0.1;
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
durationSeconds: output.format.duration ? parseFloat(output.format.duration) : 0,
|
|
122
|
+
width: videoStream.width || 0,
|
|
123
|
+
height: videoStream.height || 0,
|
|
124
|
+
fps,
|
|
125
|
+
videoCodec: videoStream.codec_name || "unknown",
|
|
126
|
+
hasAudio: output.streams.some((s) => s.codec_type === "audio"),
|
|
127
|
+
isVFR,
|
|
128
|
+
};
|
|
129
|
+
})();
|
|
88
130
|
|
|
89
|
-
try {
|
|
90
|
-
const output: FFProbeOutput = JSON.parse(stdout);
|
|
91
|
-
const videoStream = output.streams.find((s) => s.codec_type === "video");
|
|
92
|
-
if (!videoStream) {
|
|
93
|
-
reject(new Error("[FFmpeg] No video stream found"));
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const hasAudio = output.streams.some((s) => s.codec_type === "audio");
|
|
98
|
-
const fps =
|
|
99
|
-
parseFrameRate(videoStream.avg_frame_rate) || parseFrameRate(videoStream.r_frame_rate);
|
|
100
|
-
const durationSeconds = output.format.duration ? parseFloat(output.format.duration) : 0;
|
|
101
|
-
|
|
102
|
-
const metadata: VideoMetadata = {
|
|
103
|
-
durationSeconds,
|
|
104
|
-
width: videoStream.width || 0,
|
|
105
|
-
height: videoStream.height || 0,
|
|
106
|
-
fps,
|
|
107
|
-
videoCodec: videoStream.codec_name || "unknown",
|
|
108
|
-
hasAudio,
|
|
109
|
-
};
|
|
110
|
-
resolve(metadata);
|
|
111
|
-
} catch (parseError: unknown) {
|
|
112
|
-
reject(
|
|
113
|
-
new Error(
|
|
114
|
-
`[FFmpeg] Failed to parse ffprobe output: ${parseError instanceof Error ? parseError.message : parseError}`,
|
|
115
|
-
),
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
ffprobe.on("error", (err) => {
|
|
121
|
-
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
122
|
-
reject(new Error("[FFmpeg] ffprobe not found. Please install FFmpeg."));
|
|
123
|
-
} else {
|
|
124
|
-
reject(err);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
131
|
videoMetadataCache.set(filePath, probePromise);
|
|
129
132
|
probePromise.catch(() => {
|
|
130
133
|
if (videoMetadataCache.get(filePath) === probePromise) {
|
|
@@ -136,12 +139,10 @@ export async function extractVideoMetadata(filePath: string): Promise<VideoMetad
|
|
|
136
139
|
|
|
137
140
|
export async function extractAudioMetadata(filePath: string): Promise<AudioMetadata> {
|
|
138
141
|
const cached = audioMetadataCache.get(filePath);
|
|
139
|
-
if (cached)
|
|
140
|
-
return cached;
|
|
141
|
-
}
|
|
142
|
+
if (cached) return cached;
|
|
142
143
|
|
|
143
|
-
const probePromise =
|
|
144
|
-
const
|
|
144
|
+
const probePromise = (async (): Promise<AudioMetadata> => {
|
|
145
|
+
const stdout = await runFfprobe([
|
|
145
146
|
"-v",
|
|
146
147
|
"quiet",
|
|
147
148
|
"-print_format",
|
|
@@ -149,60 +150,22 @@ export async function extractAudioMetadata(filePath: string): Promise<AudioMetad
|
|
|
149
150
|
"-show_format",
|
|
150
151
|
"-show_streams",
|
|
151
152
|
filePath,
|
|
152
|
-
];
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
reject(new Error(`[FFmpeg] ffprobe exited with code ${code}: ${stderr}`));
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
const output: FFProbeOutput = JSON.parse(stdout);
|
|
173
|
-
const audioStream = output.streams.find((s) => s.codec_type === "audio");
|
|
174
|
-
if (!audioStream) {
|
|
175
|
-
reject(new Error("[FFmpeg] No audio stream found"));
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const durationSeconds = output.format.duration ? parseFloat(output.format.duration) : 0;
|
|
180
|
-
|
|
181
|
-
const metadata: AudioMetadata = {
|
|
182
|
-
durationSeconds,
|
|
183
|
-
sampleRate: audioStream.sample_rate ? parseInt(audioStream.sample_rate) : 44100,
|
|
184
|
-
channels: audioStream.channels || 2,
|
|
185
|
-
audioCodec: audioStream.codec_name || "unknown",
|
|
186
|
-
bitrate: output.format.bit_rate ? parseInt(output.format.bit_rate) : undefined,
|
|
187
|
-
};
|
|
188
|
-
resolve(metadata);
|
|
189
|
-
} catch (parseError: unknown) {
|
|
190
|
-
reject(
|
|
191
|
-
new Error(
|
|
192
|
-
`[FFmpeg] Failed to parse ffprobe output: ${parseError instanceof Error ? parseError.message : parseError}`,
|
|
193
|
-
),
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
});
|
|
153
|
+
]);
|
|
154
|
+
const output = parseProbeJson(stdout);
|
|
155
|
+
const audioStream = output.streams.find((s) => s.codec_type === "audio");
|
|
156
|
+
if (!audioStream) throw new Error("[FFmpeg] No audio stream found");
|
|
157
|
+
|
|
158
|
+
const durationSeconds = output.format.duration ? parseFloat(output.format.duration) : 0;
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
durationSeconds,
|
|
162
|
+
sampleRate: audioStream.sample_rate ? parseInt(audioStream.sample_rate) : 44100,
|
|
163
|
+
channels: audioStream.channels || 2,
|
|
164
|
+
audioCodec: audioStream.codec_name || "unknown",
|
|
165
|
+
bitrate: output.format.bit_rate ? parseInt(output.format.bit_rate) : undefined,
|
|
166
|
+
};
|
|
167
|
+
})();
|
|
197
168
|
|
|
198
|
-
ffprobe.on("error", (err) => {
|
|
199
|
-
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
200
|
-
reject(new Error("[FFmpeg] ffprobe not found. Please install FFmpeg."));
|
|
201
|
-
} else {
|
|
202
|
-
reject(err);
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
169
|
audioMetadataCache.set(filePath, probePromise);
|
|
207
170
|
probePromise.catch(() => {
|
|
208
171
|
if (audioMetadataCache.get(filePath) === probePromise) {
|
|
@@ -211,3 +174,77 @@ export async function extractAudioMetadata(filePath: string): Promise<AudioMetad
|
|
|
211
174
|
});
|
|
212
175
|
return probePromise;
|
|
213
176
|
}
|
|
177
|
+
|
|
178
|
+
export interface KeyframeAnalysis {
|
|
179
|
+
avgIntervalSeconds: number;
|
|
180
|
+
maxIntervalSeconds: number;
|
|
181
|
+
keyframeCount: number;
|
|
182
|
+
isProblematic: boolean;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const keyframeCache = new Map<string, Promise<KeyframeAnalysis>>();
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Check keyframe intervals in a video file. Intervals > 2s cause seeking
|
|
189
|
+
* issues in the headless renderer and audio/video desync. Videos from
|
|
190
|
+
* yt-dlp --download-sections or screen recordings often have sparse keyframes.
|
|
191
|
+
*/
|
|
192
|
+
export async function analyzeKeyframeIntervals(filePath: string): Promise<KeyframeAnalysis> {
|
|
193
|
+
const cached = keyframeCache.get(filePath);
|
|
194
|
+
if (cached) return cached;
|
|
195
|
+
|
|
196
|
+
const promise = analyzeKeyframeIntervalsUncached(filePath);
|
|
197
|
+
keyframeCache.set(filePath, promise);
|
|
198
|
+
promise.catch(() => {
|
|
199
|
+
if (keyframeCache.get(filePath) === promise) {
|
|
200
|
+
keyframeCache.delete(filePath);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
return promise;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function analyzeKeyframeIntervalsUncached(filePath: string): Promise<KeyframeAnalysis> {
|
|
207
|
+
const stdout = await runFfprobe([
|
|
208
|
+
"-v",
|
|
209
|
+
"quiet",
|
|
210
|
+
"-select_streams",
|
|
211
|
+
"v:0",
|
|
212
|
+
"-skip_frame",
|
|
213
|
+
"nokey",
|
|
214
|
+
"-show_entries",
|
|
215
|
+
"frame=pts_time",
|
|
216
|
+
"-of",
|
|
217
|
+
"csv=p=0",
|
|
218
|
+
filePath,
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
const timestamps = stdout
|
|
222
|
+
.split("\n")
|
|
223
|
+
.map((line) => parseFloat(line.trim()))
|
|
224
|
+
.filter((t) => Number.isFinite(t));
|
|
225
|
+
|
|
226
|
+
if (timestamps.length < 2) {
|
|
227
|
+
return {
|
|
228
|
+
avgIntervalSeconds: 0,
|
|
229
|
+
maxIntervalSeconds: 0,
|
|
230
|
+
keyframeCount: timestamps.length,
|
|
231
|
+
isProblematic: false,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let maxInterval = 0;
|
|
236
|
+
let totalInterval = 0;
|
|
237
|
+
for (let i = 1; i < timestamps.length; i++) {
|
|
238
|
+
const interval = (timestamps[i] ?? 0) - (timestamps[i - 1] ?? 0);
|
|
239
|
+
totalInterval += interval;
|
|
240
|
+
if (interval > maxInterval) maxInterval = interval;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const avgInterval = totalInterval / (timestamps.length - 1);
|
|
244
|
+
return {
|
|
245
|
+
avgIntervalSeconds: Math.round(avgInterval * 100) / 100,
|
|
246
|
+
maxIntervalSeconds: Math.round(maxInterval * 100) / 100,
|
|
247
|
+
keyframeCount: timestamps.length,
|
|
248
|
+
isProblematic: maxInterval > 2,
|
|
249
|
+
};
|
|
250
|
+
}
|