melies-video-editor 0.1.4 → 0.1.6

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.
@@ -1,4 +1,6 @@
1
1
  import './index.less';
2
+ import type { CusTomTimelineRow } from './mock';
3
+ import type { FootageItem } from './footageBin';
2
4
  export type MeliesVideoEditorProps = {
3
5
  /**
4
6
  * URLs (often blob: URLs) to show in the footage bin.
@@ -28,6 +30,73 @@ export type MeliesVideoEditorProps = {
28
30
  * Defaults to false.
29
31
  */
30
32
  autoPlaceFootage?: boolean;
33
+ /**
34
+ * Optional initial timeline snapshot (e.g. loaded from your DB).
35
+ *
36
+ * Note: if you store `blob:` URLs in the snapshot, they will not be valid across sessions.
37
+ * Prefer storing stable asset ids and rehydrating to playable URLs before loading.
38
+ */
39
+ initialTimelineSnapshot?: MeliesTimelineSnapshot;
40
+ /**
41
+ * Called whenever timeline state changes.
42
+ *
43
+ * Consumers should debounce/throttle this callback when persisting to a DB.
44
+ */
45
+ onTimelineStateChange?: (snapshot: MeliesTimelineSnapshot) => void;
46
+ /**
47
+ * Fired when the user imports files into the footage bin.
48
+ *
49
+ * This exposes the actual `File` objects to the host app (for upload/OPFS/storage).
50
+ * Note: imported `blob:` URLs are session-only; hosts should persist and rehydrate using
51
+ * stable asset identifiers if they need cross-session restore.
52
+ */
53
+ onFootageImported?: (event: MeliesFootageImportEvent) => void;
54
+ };
55
+ export type MeliesFootageImportEntry = {
56
+ /** The bin item added to the footage bin. */
57
+ item: FootageItem;
58
+ /** The underlying file selected by the user. */
59
+ file: File;
60
+ };
61
+ export type MeliesFootageImportEvent = {
62
+ /** Pairs each created bin item to its underlying file. */
63
+ entries: MeliesFootageImportEntry[];
64
+ /** Convenience list of items. */
65
+ items: FootageItem[];
66
+ /** Convenience list of files. */
67
+ files: File[];
68
+ };
69
+ export type MeliesTimelineSnapshot = {
70
+ /** Bump this when snapshot schema changes. */
71
+ version: 1;
72
+ /** Timeline rows/actions data (seconds). */
73
+ editorData: CusTomTimelineRow[];
74
+ /** UI selection (optional to restore). */
75
+ selectedActionId: string | null;
76
+ /** UI zoom (optional to restore). */
77
+ timelineScaleWidth: number;
78
+ };
79
+ export type MeliesVideoEditorRef = {
80
+ /**
81
+ * Get a deep-cloned snapshot of the current timeline state.
82
+ * Safe to store/mutate externally.
83
+ */
84
+ getTimelineSnapshot: () => MeliesTimelineSnapshot;
85
+ /**
86
+ * Load a snapshot into the editor.
87
+ * Resets undo/redo history.
88
+ */
89
+ setTimelineSnapshot: (snapshot: MeliesTimelineSnapshot) => void;
90
+ /**
91
+ * Get the imported `File` for a given footage item id (only for user-imported items).
92
+ * Returns null if the id was not imported this session.
93
+ */
94
+ getImportedFileByFootageId: (footageId: string) => File | null;
95
+ /** List all imported files currently known to the editor (this session). */
96
+ listImportedFiles: () => Array<{
97
+ footageId: string;
98
+ file: File;
99
+ }>;
31
100
  };
32
- declare const MeliesVideoEditor: ({ footageUrls, footageFiles, footageFileHandles, autoPlaceFootage, }: MeliesVideoEditorProps) => import("react/jsx-runtime").JSX.Element;
101
+ declare const MeliesVideoEditor: import("react").ForwardRefExoticComponent<MeliesVideoEditorProps & import("react").RefAttributes<MeliesVideoEditorRef>>;
33
102
  export default MeliesVideoEditor;
@@ -0,0 +1,2 @@
1
+ /** Compile-time version string injected by Vite (from package.json). */
2
+ export declare const APP_VERSION: string;
@@ -1,3 +1,4 @@
1
+ import './devRoot.css';
1
2
  export default function DevRoot({ defaultFootageUrls, useHostShell, }: {
2
3
  defaultFootageUrls?: string[];
3
4
  useHostShell: boolean;
@@ -1,37 +1,35 @@
1
- export type OpfsRoot = FileSystemDirectoryHandle;
2
- export declare const ensureOpfsRoot: () => Promise<OpfsRoot>;
3
- export declare const ensureDir: (root: OpfsRoot, path: string) => Promise<FileSystemDirectoryHandle>;
1
+ type OpfsRoot = FileSystemDirectoryHandle;
2
+ type Maybe<T> = T | null | undefined;
3
+ export type OpfsSupport = {
4
+ supported: boolean;
5
+ reason?: string;
6
+ };
4
7
  /**
5
- * Writes a Blob or File to OPFS.
6
- * Uses createWritable() which is the standard async way to write.
8
+ * Best-effort OPFS capability check.
9
+ *
10
+ * Notes:
11
+ * - Many browsers require a secure context (HTTPS); desktop browsers often treat localhost as secure.
12
+ * - Some mobile browsers may not implement OPFS at all.
7
13
  */
8
- export declare const writeFileToOpfs: (opts: {
14
+ export declare const getOpfsSupport: () => OpfsSupport;
15
+ export declare const ensureOpfsRoot: () => Promise<OpfsRoot>;
16
+ export declare const ensureDir: (root: OpfsRoot, path: string) => Promise<FileSystemDirectoryHandle>;
17
+ export declare const writeBlobToOpfs: (opts: {
9
18
  root: OpfsRoot;
10
19
  dirPath: string;
11
20
  fileName: string;
12
- file: Blob | File;
21
+ blob: Blob;
13
22
  }) => Promise<{
14
23
  fileHandle: FileSystemFileHandle;
15
24
  path: string;
16
25
  }>;
17
- export declare const getOpfsFile: (path: string) => Promise<File | undefined>;
18
- export declare const listFiles: (opts: {
19
- root: OpfsRoot;
20
- dirPath: string;
21
- }) => Promise<FileSystemFileHandle[]>;
22
26
  export declare const clearDir: (opts: {
23
27
  root: OpfsRoot;
24
28
  dirPath: string;
25
29
  }) => Promise<void>;
26
- type Maybe<T> = T | null | undefined;
27
- export declare const getFileFromPublicUrl: (url: string, fallbackName?: Maybe<string>) => Promise<File>;
28
- export declare const writeBlobToOpfs: (opts: {
30
+ export declare const listFiles: (opts: {
29
31
  root: OpfsRoot;
30
32
  dirPath: string;
31
- fileName: string;
32
- blob: Blob;
33
- }) => Promise<{
34
- fileHandle: FileSystemFileHandle;
35
- path: string;
36
- }>;
33
+ }) => Promise<FileSystemFileHandle[]>;
34
+ export declare const getFileFromPublicUrl: (url: string, fallbackName?: Maybe<string>) => Promise<File>;
37
35
  export {};
@@ -1,3 +1,3 @@
1
1
  export { default as MeliesVideoEditor } from '../App';
2
- export type { MeliesVideoEditorProps } from '../App';
2
+ export type { MeliesFootageImportEntry, MeliesFootageImportEvent, MeliesTimelineSnapshot, MeliesVideoEditorProps, MeliesVideoEditorRef, } from '../App';
3
3
  export type { TimelineAction, TimelineEffect, TimelineRow, TimelineState, } from '@xzdarcy/react-timeline-editor';
@@ -1,30 +1,11 @@
1
1
  type MediaKind = 'video' | 'audio' | 'other';
2
- export type ProxyEvent = {
3
- type: 'proxy-start';
4
- originalSrc: string;
5
- } | {
6
- type: 'proxy-progress';
7
- originalSrc: string;
8
- value?: number;
9
- status?: string;
10
- } | {
11
- type: 'proxy-ready';
12
- originalSrc: string;
13
- proxySrc: string;
14
- } | {
15
- type: 'proxy-failed';
16
- originalSrc: string;
17
- error: string;
18
- };
19
2
  declare const guessKind: (src: string) => MediaKind;
20
3
  declare class MediaCache {
21
4
  private blobUrlBySrc;
22
5
  private pendingBySrc;
23
6
  private metaBySrc;
24
- private proxyEventListeners;
25
- /** Subscribe to proxy generation events (useful for UI debug on mobile where console logs aren't visible). */
26
- onProxyEvent(listener: (event: ProxyEvent) => void): () => void;
27
- private emitProxyEvent;
7
+ private durationSecBySrc;
8
+ private pendingDurationBySrc;
28
9
  registerSrcMeta(src: string, meta: {
29
10
  name?: string;
30
11
  mimeType?: string;
@@ -33,24 +14,13 @@ declare class MediaCache {
33
14
  name?: string;
34
15
  mimeType?: string;
35
16
  } | undefined;
17
+ /** Returns the cached duration (seconds) if known. */
18
+ getCachedDurationSec(src: string): number | undefined;
36
19
  /**
37
- * Ingests a File object into OPFS.
38
- * Returns a virtual 'opfs://' URL that can be used as a src reference.
20
+ * Attempts to read media duration from browser metadata (seconds).
21
+ * Returns null when duration cannot be determined (e.g. unsupported/CORS/streaming).
39
22
  */
40
- ingest(file: File): Promise<string>;
41
- private initProxy;
42
- /**
43
- * Returns a URL that is safe to assign to a media element (`<video>`/`<audio>`).
44
- *
45
- * Notes:
46
- * - `opfs://...` is NOT directly playable by browsers.
47
- * - For OPFS sources, this will kick off an async preload (creating a `blob:` URL) and return `undefined`.
48
- */
49
- resolveForMediaElement(src: string): string | undefined;
50
- /**
51
- * Helper to fetch a file from OPFS given an opfs:// URL
52
- */
53
- getFileFromOpfs(opfsUrl: string): Promise<File | undefined>;
23
+ getDurationSec(src: string, kindHint?: MediaKind): Promise<number | null>;
54
24
  /**
55
25
  * Preloads a URL into memory and returns a blob: URL.
56
26
  * Useful to avoid runtime buffering/stalls when seeking frequently.
@@ -66,6 +66,26 @@ declare class VideoControl {
66
66
  warm(src: string): void;
67
67
  releaseVideo(_actionId: string): void;
68
68
  setActive(_active: boolean): void;
69
+ /**
70
+ * Returns the active (visible) video element, if any.
71
+ * Useful for UI-level logic that needs to wait for buffering after a seek.
72
+ */
73
+ getActiveVideoElement(): HTMLVideoElement | null;
74
+ /**
75
+ * Checks whether a video has at least `minSecondsAhead` buffered at its current time.
76
+ *
77
+ * Note: buffered ranges are in media time, not timeline time.
78
+ */
79
+ private hasBufferedAhead;
80
+ /**
81
+ * Waits until the active element appears ready for smooth playback after a seek.
82
+ * Returns true if the readiness criteria is met before timing out.
83
+ */
84
+ waitForActiveBufferedAhead(opts?: {
85
+ minSecondsAhead?: number;
86
+ timeoutMs?: number;
87
+ pollMs?: number;
88
+ }): Promise<boolean>;
69
89
  }
70
90
  declare const _default: VideoControl;
71
91
  export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "melies-video-editor",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "A React video timeline editor GUI built on @xzdarcy/react-timeline-editor.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,19 +0,0 @@
1
- declare class ProxyManager {
2
- private activeJobs;
3
- /**
4
- * Create (or reuse) a proxy file for an OPFS video.
5
- *
6
- * `originalOpfsPath` should be an `opfs://...` URL.
7
- */
8
- createProxy(originalOpfsPath: string, opts?: {
9
- onProgress?: (info: {
10
- value?: number;
11
- status?: string;
12
- }) => void;
13
- }): Promise<string>;
14
- private _runWorker;
15
- private getHandle;
16
- private ensureDir;
17
- }
18
- export declare const proxyManager: ProxyManager;
19
- export {};
@@ -1 +0,0 @@
1
- export {};