@remotion/media 4.0.403 → 4.0.404
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/audio/audio-for-preview.d.ts +2 -0
- package/dist/audio/audio-preview-iterator.d.ts +8 -3
- package/dist/audio/props.d.ts +2 -0
- package/dist/audio-extraction/audio-iterator.d.ts +5 -4
- package/dist/audio-extraction/audio-manager.d.ts +23 -7
- package/dist/audio-extraction/extract-audio.d.ts +2 -4
- package/dist/audio-iterator-manager.d.ts +2 -2
- package/dist/caches.d.ts +29 -11
- package/dist/convert-audiodata/apply-volume.d.ts +1 -1
- package/dist/convert-audiodata/resample-audiodata.d.ts +2 -2
- package/dist/debug-overlay/preview-overlay.d.ts +83 -5
- package/dist/esm/index.mjs +180 -146
- package/dist/extract-frame-and-audio.d.ts +1 -2
- package/dist/get-sink.d.ts +1 -2
- package/dist/index.d.ts +2 -1
- package/dist/media-player.d.ts +1 -1
- package/dist/on-error.d.ts +12 -0
- package/dist/show-in-timeline.d.ts +2 -2
- package/dist/use-media-in-timeline.d.ts +2 -2
- package/dist/video/props.d.ts +5 -0
- package/dist/video/video-for-preview.d.ts +2 -0
- package/dist/video/video-for-rendering.d.ts +2 -0
- package/dist/video/video-preview-iterator.d.ts +7 -2
- package/dist/video-extraction/extract-frame-via-broadcast-channel.d.ts +1 -2
- package/dist/video-extraction/extract-frame.d.ts +1 -3
- package/dist/video-extraction/keyframe-bank.d.ts +2 -2
- package/dist/video-extraction/keyframe-manager.d.ts +2 -3
- package/dist/video-iterator-manager.d.ts +4 -5
- package/package.json +8 -7
- package/dist/audio/allow-wait.js +0 -15
- package/dist/audio/audio-for-preview.js +0 -302
- package/dist/audio/audio-for-rendering.js +0 -196
- package/dist/audio/audio-preview-iterator.js +0 -176
- package/dist/audio/audio.js +0 -20
- package/dist/audio/props.js +0 -1
- package/dist/audio-extraction/audio-cache.js +0 -66
- package/dist/audio-extraction/audio-iterator.js +0 -132
- package/dist/audio-extraction/audio-manager.js +0 -121
- package/dist/audio-extraction/extract-audio.js +0 -132
- package/dist/audio-iterator-manager.js +0 -228
- package/dist/browser-can-use-webgl2.js +0 -13
- package/dist/caches.js +0 -61
- package/dist/calculate-playbacktime.js +0 -4
- package/dist/convert-audiodata/apply-volume.js +0 -17
- package/dist/convert-audiodata/combine-audiodata.js +0 -23
- package/dist/convert-audiodata/convert-audiodata.js +0 -73
- package/dist/convert-audiodata/resample-audiodata.js +0 -94
- package/dist/debug-overlay/preview-overlay.js +0 -44
- package/dist/extract-frame-and-audio.js +0 -86
- package/dist/get-sink.js +0 -15
- package/dist/get-time-in-seconds.js +0 -40
- package/dist/helpers/round-to-4-digits.js +0 -4
- package/dist/index.js +0 -12
- package/dist/is-type-of-error.js +0 -20
- package/dist/looped-frame.js +0 -10
- package/dist/media-player.js +0 -445
- package/dist/nonce-manager.js +0 -13
- package/dist/prewarm-iterator-for-looping.js +0 -56
- package/dist/render-timestamp-range.js +0 -9
- package/dist/show-in-timeline.js +0 -31
- package/dist/use-media-in-timeline.js +0 -103
- package/dist/video/props.js +0 -1
- package/dist/video/video-for-preview.js +0 -329
- package/dist/video/video-for-rendering.js +0 -263
- package/dist/video/video-preview-iterator.js +0 -122
- package/dist/video/video.js +0 -33
- package/dist/video-extraction/add-broadcast-channel-listener.js +0 -125
- package/dist/video-extraction/extract-frame-via-broadcast-channel.js +0 -113
- package/dist/video-extraction/extract-frame.js +0 -84
- package/dist/video-extraction/get-allocation-size.js +0 -6
- package/dist/video-extraction/get-frames-since-keyframe.js +0 -105
- package/dist/video-extraction/keyframe-bank.js +0 -200
- package/dist/video-extraction/keyframe-manager.js +0 -201
- package/dist/video-extraction/remember-actual-matroska-timestamps.js +0 -19
- package/dist/video-extraction/rotate-frame.js +0 -34
- package/dist/video-iterator-manager.js +0 -109
package/dist/esm/index.mjs
CHANGED
|
@@ -1344,6 +1344,27 @@ class MediaPlayer {
|
|
|
1344
1344
|
};
|
|
1345
1345
|
}
|
|
1346
1346
|
|
|
1347
|
+
// src/on-error.ts
|
|
1348
|
+
var callOnErrorAndResolve = ({
|
|
1349
|
+
onError,
|
|
1350
|
+
error,
|
|
1351
|
+
disallowFallback,
|
|
1352
|
+
isClientSideRendering,
|
|
1353
|
+
clientSideError
|
|
1354
|
+
}) => {
|
|
1355
|
+
const result = onError?.(error);
|
|
1356
|
+
if (isClientSideRendering) {
|
|
1357
|
+
return ["fail", clientSideError];
|
|
1358
|
+
}
|
|
1359
|
+
if (result) {
|
|
1360
|
+
return [result, error];
|
|
1361
|
+
}
|
|
1362
|
+
if (disallowFallback) {
|
|
1363
|
+
return ["fail", error];
|
|
1364
|
+
}
|
|
1365
|
+
return ["fallback", error];
|
|
1366
|
+
};
|
|
1367
|
+
|
|
1347
1368
|
// src/show-in-timeline.ts
|
|
1348
1369
|
import { useMemo } from "react";
|
|
1349
1370
|
import { Internals as Internals4, useVideoConfig } from "remotion";
|
|
@@ -1538,7 +1559,8 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1538
1559
|
disallowFallbackToHtml5Audio,
|
|
1539
1560
|
toneFrequency,
|
|
1540
1561
|
audioStreamIndex,
|
|
1541
|
-
fallbackHtml5AudioProps
|
|
1562
|
+
fallbackHtml5AudioProps,
|
|
1563
|
+
onError
|
|
1542
1564
|
}) => {
|
|
1543
1565
|
const videoConfig = useUnsafeVideoConfig();
|
|
1544
1566
|
const frame = useCurrentFrame2();
|
|
@@ -1637,36 +1659,35 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1637
1659
|
if (result.type === "disposed") {
|
|
1638
1660
|
return;
|
|
1639
1661
|
}
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1662
|
+
const handleError = (error, fallbackMessage) => {
|
|
1663
|
+
const [action, errorToUse] = callOnErrorAndResolve({
|
|
1664
|
+
onError,
|
|
1665
|
+
error,
|
|
1666
|
+
disallowFallback: disallowFallbackToHtml5Audio,
|
|
1667
|
+
isClientSideRendering: false,
|
|
1668
|
+
clientSideError: error
|
|
1669
|
+
});
|
|
1670
|
+
if (action === "fail") {
|
|
1671
|
+
throw errorToUse;
|
|
1672
|
+
} else {
|
|
1673
|
+
Internals6.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
|
|
1674
|
+
setShouldFallbackToNativeAudio(true);
|
|
1643
1675
|
}
|
|
1644
|
-
|
|
1645
|
-
|
|
1676
|
+
};
|
|
1677
|
+
if (result.type === "unknown-container-format") {
|
|
1678
|
+
handleError(new Error(`Unknown container format ${preloadedSrc}.`), `Unknown container format for ${preloadedSrc} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <Html5Audio>`);
|
|
1646
1679
|
return;
|
|
1647
1680
|
}
|
|
1648
1681
|
if (result.type === "network-error") {
|
|
1649
|
-
|
|
1650
|
-
throw new Error(`Network error fetching ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
|
|
1651
|
-
}
|
|
1652
|
-
Internals6.Log.warn({ logLevel, tag: "@remotion/media" }, `Network error fetching ${preloadedSrc}, falling back to <Html5Audio>`);
|
|
1653
|
-
setShouldFallbackToNativeAudio(true);
|
|
1682
|
+
handleError(new Error(`Network error fetching ${preloadedSrc}.`), `Network error fetching ${preloadedSrc}, falling back to <Html5Audio>`);
|
|
1654
1683
|
return;
|
|
1655
1684
|
}
|
|
1656
1685
|
if (result.type === "cannot-decode") {
|
|
1657
|
-
|
|
1658
|
-
throw new Error(`Cannot decode ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
|
|
1659
|
-
}
|
|
1660
|
-
Internals6.Log.warn({ logLevel, tag: "@remotion/media" }, `Cannot decode ${preloadedSrc}, falling back to <Html5Audio>`);
|
|
1661
|
-
setShouldFallbackToNativeAudio(true);
|
|
1686
|
+
handleError(new Error(`Cannot decode ${preloadedSrc}.`), `Cannot decode ${preloadedSrc}, falling back to <Html5Audio>`);
|
|
1662
1687
|
return;
|
|
1663
1688
|
}
|
|
1664
1689
|
if (result.type === "no-tracks") {
|
|
1665
|
-
|
|
1666
|
-
throw new Error(`No video or audio tracks found for ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
|
|
1667
|
-
}
|
|
1668
|
-
Internals6.Log.warn({ logLevel, tag: "@remotion/media" }, `No video or audio tracks found for ${preloadedSrc}, falling back to <Html5Audio>`);
|
|
1669
|
-
setShouldFallbackToNativeAudio(true);
|
|
1690
|
+
handleError(new Error(`No video or audio tracks found for ${preloadedSrc}.`), `No video or audio tracks found for ${preloadedSrc}, falling back to <Html5Audio>`);
|
|
1670
1691
|
return;
|
|
1671
1692
|
}
|
|
1672
1693
|
if (result.type === "success") {
|
|
@@ -1675,11 +1696,32 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1675
1696
|
Internals6.Log.trace({ logLevel, tag: "@remotion/media" }, `[AudioForPreview] MediaPlayer initialized successfully`);
|
|
1676
1697
|
}
|
|
1677
1698
|
}).catch((error) => {
|
|
1678
|
-
|
|
1679
|
-
|
|
1699
|
+
const [action, errorToUse] = callOnErrorAndResolve({
|
|
1700
|
+
onError,
|
|
1701
|
+
error,
|
|
1702
|
+
disallowFallback: disallowFallbackToHtml5Audio,
|
|
1703
|
+
isClientSideRendering: false,
|
|
1704
|
+
clientSideError: error
|
|
1705
|
+
});
|
|
1706
|
+
if (action === "fail") {
|
|
1707
|
+
throw errorToUse;
|
|
1708
|
+
} else {
|
|
1709
|
+
Internals6.Log.error({ logLevel, tag: "@remotion/media" }, "[AudioForPreview] Failed to initialize MediaPlayer", error);
|
|
1710
|
+
setShouldFallbackToNativeAudio(true);
|
|
1711
|
+
}
|
|
1680
1712
|
});
|
|
1681
1713
|
} catch (error) {
|
|
1682
|
-
|
|
1714
|
+
const [action, errorToUse] = callOnErrorAndResolve({
|
|
1715
|
+
error,
|
|
1716
|
+
onError,
|
|
1717
|
+
disallowFallback: disallowFallbackToHtml5Audio,
|
|
1718
|
+
isClientSideRendering: false,
|
|
1719
|
+
clientSideError: error
|
|
1720
|
+
});
|
|
1721
|
+
if (action === "fail") {
|
|
1722
|
+
throw errorToUse;
|
|
1723
|
+
}
|
|
1724
|
+
Internals6.Log.error({ logLevel, tag: "@remotion/media" }, "[AudioForPreview] MediaPlayer initialization failed", errorToUse);
|
|
1683
1725
|
setShouldFallbackToNativeAudio(true);
|
|
1684
1726
|
}
|
|
1685
1727
|
return () => {
|
|
@@ -1700,7 +1742,8 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1700
1742
|
videoConfig.fps,
|
|
1701
1743
|
audioStreamIndex,
|
|
1702
1744
|
disallowFallbackToHtml5Audio,
|
|
1703
|
-
buffer
|
|
1745
|
+
buffer,
|
|
1746
|
+
onError
|
|
1704
1747
|
]);
|
|
1705
1748
|
useLayoutEffect(() => {
|
|
1706
1749
|
const audioPlayer = mediaPlayerRef.current;
|
|
@@ -1827,7 +1870,8 @@ var AudioForPreview = ({
|
|
|
1827
1870
|
disallowFallbackToHtml5Audio,
|
|
1828
1871
|
toneFrequency,
|
|
1829
1872
|
audioStreamIndex,
|
|
1830
|
-
fallbackHtml5AudioProps
|
|
1873
|
+
fallbackHtml5AudioProps,
|
|
1874
|
+
onError
|
|
1831
1875
|
}) => {
|
|
1832
1876
|
const preloadedSrc = usePreload(src);
|
|
1833
1877
|
const defaultLogLevel = Internals6.useLogLevel();
|
|
@@ -1874,6 +1918,7 @@ var AudioForPreview = ({
|
|
|
1874
1918
|
stack,
|
|
1875
1919
|
disallowFallbackToHtml5Audio: disallowFallbackToHtml5Audio ?? false,
|
|
1876
1920
|
toneFrequency,
|
|
1921
|
+
onError,
|
|
1877
1922
|
fallbackHtml5AudioProps
|
|
1878
1923
|
});
|
|
1879
1924
|
};
|
|
@@ -2498,7 +2543,7 @@ var makeKeyframeManager = () => {
|
|
|
2498
2543
|
}
|
|
2499
2544
|
return { mostInThePastBank, numberOfBanks };
|
|
2500
2545
|
};
|
|
2501
|
-
const deleteOldestKeyframeBank =
|
|
2546
|
+
const deleteOldestKeyframeBank = (logLevel) => {
|
|
2502
2547
|
const {
|
|
2503
2548
|
mostInThePastBank: {
|
|
2504
2549
|
bank: mostInThePastBank,
|
|
@@ -2506,31 +2551,31 @@ var makeKeyframeManager = () => {
|
|
|
2506
2551
|
index: mostInThePastIndex
|
|
2507
2552
|
},
|
|
2508
2553
|
numberOfBanks
|
|
2509
|
-
} =
|
|
2554
|
+
} = getTheKeyframeBankMostInThePast();
|
|
2510
2555
|
if (numberOfBanks < 2) {
|
|
2511
2556
|
return { finish: true };
|
|
2512
2557
|
}
|
|
2513
2558
|
if (mostInThePastBank) {
|
|
2514
2559
|
const range = mostInThePastBank.getRangeOfTimestamps();
|
|
2515
2560
|
const { framesDeleted } = mostInThePastBank.prepareForDeletion(logLevel, "deleted oldest keyframe bank to stay under max cache size");
|
|
2516
|
-
|
|
2561
|
+
sources[mostInThePastSrc].splice(mostInThePastIndex, 1);
|
|
2517
2562
|
if (range) {
|
|
2518
2563
|
Internals10.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted ${framesDeleted} frames for src ${mostInThePastSrc} from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec to free up memory.`);
|
|
2519
2564
|
}
|
|
2520
2565
|
}
|
|
2521
2566
|
return { finish: false };
|
|
2522
2567
|
};
|
|
2523
|
-
const ensureToStayUnderMaxCacheSize =
|
|
2524
|
-
let cacheStats =
|
|
2568
|
+
const ensureToStayUnderMaxCacheSize = (logLevel, maxCacheSize) => {
|
|
2569
|
+
let cacheStats = getTotalCacheStats();
|
|
2525
2570
|
let attempts = 0;
|
|
2526
2571
|
const maxAttempts = 3;
|
|
2527
2572
|
while (cacheStats.totalSize > maxCacheSize && attempts < maxAttempts) {
|
|
2528
|
-
const { finish } =
|
|
2573
|
+
const { finish } = deleteOldestKeyframeBank(logLevel);
|
|
2529
2574
|
if (finish) {
|
|
2530
2575
|
break;
|
|
2531
2576
|
}
|
|
2532
2577
|
Internals10.Log.verbose({ logLevel, tag: "@remotion/media" }, "Deleted oldest keyframe bank to stay under max cache size", (cacheStats.totalSize / 1024 / 1024).toFixed(1), "out of", (maxCacheSize / 1024 / 1024).toFixed(1));
|
|
2533
|
-
cacheStats =
|
|
2578
|
+
cacheStats = getTotalCacheStats();
|
|
2534
2579
|
attempts++;
|
|
2535
2580
|
}
|
|
2536
2581
|
if (cacheStats.totalSize > maxCacheSize && attempts >= maxAttempts) {
|
|
@@ -2610,7 +2655,7 @@ var makeKeyframeManager = () => {
|
|
|
2610
2655
|
logLevel,
|
|
2611
2656
|
maxCacheSize
|
|
2612
2657
|
}) => {
|
|
2613
|
-
|
|
2658
|
+
ensureToStayUnderMaxCacheSize(logLevel, maxCacheSize);
|
|
2614
2659
|
clearKeyframeBanksBeforeTime({
|
|
2615
2660
|
timestampInSeconds: timestamp,
|
|
2616
2661
|
src,
|
|
@@ -2662,8 +2707,8 @@ var makeKeyframeManager = () => {
|
|
|
2662
2707
|
var SAFE_WINDOW_OF_MONOTONICITY = 0.2;
|
|
2663
2708
|
var keyframeManager = makeKeyframeManager();
|
|
2664
2709
|
var audioManager = makeAudioManager();
|
|
2665
|
-
var getTotalCacheStats =
|
|
2666
|
-
const keyframeManagerCacheStats =
|
|
2710
|
+
var getTotalCacheStats = () => {
|
|
2711
|
+
const keyframeManagerCacheStats = keyframeManager.getCacheStats();
|
|
2667
2712
|
const audioManagerCacheStats = audioManager.getCacheStats();
|
|
2668
2713
|
return {
|
|
2669
2714
|
count: keyframeManagerCacheStats.count + audioManagerCacheStats.count,
|
|
@@ -3697,7 +3742,8 @@ var AudioForRendering = ({
|
|
|
3697
3742
|
disallowFallbackToHtml5Audio,
|
|
3698
3743
|
toneFrequency,
|
|
3699
3744
|
trimAfter,
|
|
3700
|
-
trimBefore
|
|
3745
|
+
trimBefore,
|
|
3746
|
+
onError
|
|
3701
3747
|
}) => {
|
|
3702
3748
|
const defaultLogLevel = Internals14.useLogLevel();
|
|
3703
3749
|
const logLevel = overriddenLogLevel ?? defaultLogLevel;
|
|
@@ -3763,52 +3809,33 @@ var AudioForRendering = ({
|
|
|
3763
3809
|
fps,
|
|
3764
3810
|
maxCacheSize
|
|
3765
3811
|
}).then((result) => {
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3812
|
+
const handleError = (error, clientSideError, fallbackMessage) => {
|
|
3813
|
+
const [action, errorToUse] = callOnErrorAndResolve({
|
|
3814
|
+
onError,
|
|
3815
|
+
error,
|
|
3816
|
+
disallowFallback: disallowFallbackToHtml5Audio ?? false,
|
|
3817
|
+
isClientSideRendering: environment.isClientSideRendering,
|
|
3818
|
+
clientSideError
|
|
3819
|
+
});
|
|
3820
|
+
if (action === "fail") {
|
|
3821
|
+
cancelRender2(errorToUse);
|
|
3773
3822
|
}
|
|
3774
|
-
Internals14.Log.warn({
|
|
3775
|
-
logLevel,
|
|
3776
|
-
tag: "@remotion/media"
|
|
3777
|
-
}, `Unknown container format for ${src} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <Html5Audio>`);
|
|
3823
|
+
Internals14.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
|
|
3778
3824
|
setReplaceWithHtml5Audio(true);
|
|
3825
|
+
};
|
|
3826
|
+
if (result.type === "unknown-container-format") {
|
|
3827
|
+
handleError(new Error(`Unknown container format ${src}.`), new Error(`Cannot render audio "${src}": Unknown container format. See supported formats: https://www.remotion.dev/docs/mediabunny/formats`), `Unknown container format for ${src} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <Html5Audio>`);
|
|
3779
3828
|
return;
|
|
3780
3829
|
}
|
|
3781
3830
|
if (result.type === "cannot-decode") {
|
|
3782
|
-
|
|
3783
|
-
cancelRender2(new Error(`Cannot render audio "${src}": The audio could not be decoded by the browser.`));
|
|
3784
|
-
return;
|
|
3785
|
-
}
|
|
3786
|
-
if (disallowFallbackToHtml5Audio) {
|
|
3787
|
-
cancelRender2(new Error(`Cannot decode ${src}, and 'disallowFallbackToHtml5Audio' was set. Failing the render.`));
|
|
3788
|
-
}
|
|
3789
|
-
Internals14.Log.warn({
|
|
3790
|
-
logLevel,
|
|
3791
|
-
tag: "@remotion/media"
|
|
3792
|
-
}, `Cannot decode ${src}, falling back to <Html5Audio>`);
|
|
3793
|
-
setReplaceWithHtml5Audio(true);
|
|
3831
|
+
handleError(new Error(`Cannot decode ${src}.`), new Error(`Cannot render audio "${src}": The audio could not be decoded by the browser.`), `Cannot decode ${src}, falling back to <Html5Audio>`);
|
|
3794
3832
|
return;
|
|
3795
3833
|
}
|
|
3796
3834
|
if (result.type === "cannot-decode-alpha") {
|
|
3797
3835
|
throw new Error(`Cannot decode alpha component for ${src}, and 'disallowFallbackToHtml5Audio' was set. But this should never happen, since you used the <Audio> tag. Please report this as a bug.`);
|
|
3798
3836
|
}
|
|
3799
3837
|
if (result.type === "network-error") {
|
|
3800
|
-
|
|
3801
|
-
cancelRender2(new Error(`Cannot render audio "${src}": Network error while fetching the audio (possibly CORS).`));
|
|
3802
|
-
return;
|
|
3803
|
-
}
|
|
3804
|
-
if (disallowFallbackToHtml5Audio) {
|
|
3805
|
-
cancelRender2(new Error(`Cannot decode ${src}, and 'disallowFallbackToHtml5Audio' was set. Failing the render.`));
|
|
3806
|
-
}
|
|
3807
|
-
Internals14.Log.warn({
|
|
3808
|
-
logLevel,
|
|
3809
|
-
tag: "@remotion/media"
|
|
3810
|
-
}, `Network error fetching ${src}, falling back to <Html5Audio>`);
|
|
3811
|
-
setReplaceWithHtml5Audio(true);
|
|
3838
|
+
handleError(new Error(`Network error fetching ${src}.`), new Error(`Cannot render audio "${src}": Network error while fetching the audio (possibly CORS).`), `Network error fetching ${src}, falling back to <Html5Audio>`);
|
|
3812
3839
|
return;
|
|
3813
3840
|
}
|
|
3814
3841
|
const { audio, durationInSeconds: assetDurationInSeconds } = result;
|
|
@@ -3873,7 +3900,8 @@ var AudioForRendering = ({
|
|
|
3873
3900
|
trimBefore,
|
|
3874
3901
|
replaceWithHtml5Audio,
|
|
3875
3902
|
maxCacheSize,
|
|
3876
|
-
audioEnabled
|
|
3903
|
+
audioEnabled,
|
|
3904
|
+
onError
|
|
3877
3905
|
]);
|
|
3878
3906
|
if (replaceWithHtml5Audio) {
|
|
3879
3907
|
return /* @__PURE__ */ jsx2(Html5Audio, {
|
|
@@ -3974,7 +4002,8 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
3974
4002
|
fallbackOffthreadVideoProps,
|
|
3975
4003
|
audioStreamIndex,
|
|
3976
4004
|
debugOverlay,
|
|
3977
|
-
headless
|
|
4005
|
+
headless,
|
|
4006
|
+
onError
|
|
3978
4007
|
}) => {
|
|
3979
4008
|
const src = usePreload2(unpreloadedSrc);
|
|
3980
4009
|
const canvasRef = useRef2(null);
|
|
@@ -4073,36 +4102,34 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4073
4102
|
if (result.type === "disposed") {
|
|
4074
4103
|
return;
|
|
4075
4104
|
}
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4105
|
+
const handleError = (error, fallbackMessage) => {
|
|
4106
|
+
const [action, errorToUse] = callOnErrorAndResolve({
|
|
4107
|
+
onError,
|
|
4108
|
+
error,
|
|
4109
|
+
disallowFallback: disallowFallbackToOffthreadVideo,
|
|
4110
|
+
isClientSideRendering: false,
|
|
4111
|
+
clientSideError: error
|
|
4112
|
+
});
|
|
4113
|
+
if (action === "fail") {
|
|
4114
|
+
throw errorToUse;
|
|
4079
4115
|
}
|
|
4080
|
-
Internals16.Log.warn({ logLevel, tag: "@remotion/media" },
|
|
4116
|
+
Internals16.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
|
|
4081
4117
|
setShouldFallbackToNativeVideo(true);
|
|
4118
|
+
};
|
|
4119
|
+
if (result.type === "unknown-container-format") {
|
|
4120
|
+
handleError(new Error(`Unknown container format ${preloadedSrc}.`), `Unknown container format for ${preloadedSrc} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <OffthreadVideo>`);
|
|
4082
4121
|
return;
|
|
4083
4122
|
}
|
|
4084
4123
|
if (result.type === "network-error") {
|
|
4085
|
-
|
|
4086
|
-
throw new Error(`Network error fetching ${preloadedSrc}, and 'disallowFallbackToOffthreadVideo' was set.`);
|
|
4087
|
-
}
|
|
4088
|
-
Internals16.Log.warn({ logLevel, tag: "@remotion/media" }, `Network error fetching ${preloadedSrc}, falling back to <OffthreadVideo>`);
|
|
4089
|
-
setShouldFallbackToNativeVideo(true);
|
|
4124
|
+
handleError(new Error(`Network error fetching ${preloadedSrc}.`), `Network error fetching ${preloadedSrc}, falling back to <OffthreadVideo>`);
|
|
4090
4125
|
return;
|
|
4091
4126
|
}
|
|
4092
4127
|
if (result.type === "cannot-decode") {
|
|
4093
|
-
|
|
4094
|
-
throw new Error(`Cannot decode ${preloadedSrc}, and 'disallowFallbackToOffthreadVideo' was set.`);
|
|
4095
|
-
}
|
|
4096
|
-
Internals16.Log.warn({ logLevel, tag: "@remotion/media" }, `Cannot decode ${preloadedSrc}, falling back to <OffthreadVideo>`);
|
|
4097
|
-
setShouldFallbackToNativeVideo(true);
|
|
4128
|
+
handleError(new Error(`Cannot decode ${preloadedSrc}.`), `Cannot decode ${preloadedSrc}, falling back to <OffthreadVideo>`);
|
|
4098
4129
|
return;
|
|
4099
4130
|
}
|
|
4100
4131
|
if (result.type === "no-tracks") {
|
|
4101
|
-
|
|
4102
|
-
throw new Error(`No video or audio tracks found for ${preloadedSrc}, and 'disallowFallbackToOffthreadVideo' was set.`);
|
|
4103
|
-
}
|
|
4104
|
-
Internals16.Log.warn({ logLevel, tag: "@remotion/media" }, `No video or audio tracks found for ${preloadedSrc}, falling back to <OffthreadVideo>`);
|
|
4105
|
-
setShouldFallbackToNativeVideo(true);
|
|
4132
|
+
handleError(new Error(`No video or audio tracks found for ${preloadedSrc}.`), `No video or audio tracks found for ${preloadedSrc}, falling back to <OffthreadVideo>`);
|
|
4106
4133
|
return;
|
|
4107
4134
|
}
|
|
4108
4135
|
if (result.type === "success") {
|
|
@@ -4110,11 +4137,31 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4110
4137
|
setMediaDurationInSeconds(result.durationInSeconds);
|
|
4111
4138
|
}
|
|
4112
4139
|
}).catch((error) => {
|
|
4113
|
-
|
|
4140
|
+
const [action, errorToUse] = callOnErrorAndResolve({
|
|
4141
|
+
onError,
|
|
4142
|
+
error,
|
|
4143
|
+
disallowFallback: disallowFallbackToOffthreadVideo,
|
|
4144
|
+
isClientSideRendering: false,
|
|
4145
|
+
clientSideError: error
|
|
4146
|
+
});
|
|
4147
|
+
if (action === "fail") {
|
|
4148
|
+
throw errorToUse;
|
|
4149
|
+
}
|
|
4150
|
+
Internals16.Log.error({ logLevel, tag: "@remotion/media" }, "[VideoForPreview] Failed to initialize MediaPlayer", errorToUse);
|
|
4114
4151
|
setShouldFallbackToNativeVideo(true);
|
|
4115
4152
|
});
|
|
4116
4153
|
} catch (error) {
|
|
4117
|
-
|
|
4154
|
+
const [action, errorToUse] = callOnErrorAndResolve({
|
|
4155
|
+
error,
|
|
4156
|
+
onError,
|
|
4157
|
+
disallowFallback: disallowFallbackToOffthreadVideo,
|
|
4158
|
+
isClientSideRendering: false,
|
|
4159
|
+
clientSideError: error
|
|
4160
|
+
});
|
|
4161
|
+
if (action === "fail") {
|
|
4162
|
+
throw errorToUse;
|
|
4163
|
+
}
|
|
4164
|
+
Internals16.Log.error({ logLevel, tag: "@remotion/media" }, "[VideoForPreview] MediaPlayer initialization failed", errorToUse);
|
|
4118
4165
|
setShouldFallbackToNativeVideo(true);
|
|
4119
4166
|
}
|
|
4120
4167
|
return () => {
|
|
@@ -4135,7 +4182,8 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4135
4182
|
loop,
|
|
4136
4183
|
preloadedSrc,
|
|
4137
4184
|
sharedAudioContext,
|
|
4138
|
-
videoConfig.fps
|
|
4185
|
+
videoConfig.fps,
|
|
4186
|
+
onError
|
|
4139
4187
|
]);
|
|
4140
4188
|
const classNameValue = useMemo4(() => {
|
|
4141
4189
|
return [Internals16.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals16.truthy).join(" ");
|
|
@@ -4348,7 +4396,8 @@ var VideoForRendering = ({
|
|
|
4348
4396
|
toneFrequency,
|
|
4349
4397
|
trimAfterValue,
|
|
4350
4398
|
trimBeforeValue,
|
|
4351
|
-
headless
|
|
4399
|
+
headless,
|
|
4400
|
+
onError
|
|
4352
4401
|
}) => {
|
|
4353
4402
|
if (!src) {
|
|
4354
4403
|
throw new TypeError("No `src` was passed to <Video>.");
|
|
@@ -4417,64 +4466,43 @@ var VideoForRendering = ({
|
|
|
4417
4466
|
fps,
|
|
4418
4467
|
maxCacheSize
|
|
4419
4468
|
}).then((result) => {
|
|
4420
|
-
|
|
4469
|
+
const handleError = (err, clientSideError, fallbackMessage, mediaDurationInSeconds) => {
|
|
4421
4470
|
if (environment.isClientSideRendering) {
|
|
4422
|
-
cancelRender3(
|
|
4471
|
+
cancelRender3(clientSideError);
|
|
4423
4472
|
return;
|
|
4424
4473
|
}
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
if (result.type === "cannot-decode") {
|
|
4435
|
-
if (environment.isClientSideRendering) {
|
|
4436
|
-
cancelRender3(new Error(`Cannot render video "${src}": The video could not be decoded by the browser.`));
|
|
4474
|
+
const [action, errorToUse] = callOnErrorAndResolve({
|
|
4475
|
+
onError,
|
|
4476
|
+
error: err,
|
|
4477
|
+
disallowFallback: disallowFallbackToOffthreadVideo,
|
|
4478
|
+
isClientSideRendering: environment.isClientSideRendering,
|
|
4479
|
+
clientSideError: err
|
|
4480
|
+
});
|
|
4481
|
+
if (action === "fail") {
|
|
4482
|
+
cancelRender3(errorToUse);
|
|
4437
4483
|
return;
|
|
4438
4484
|
}
|
|
4439
|
-
if (disallowFallbackToOffthreadVideo) {
|
|
4440
|
-
cancelRender3(new Error(`Cannot decode ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
|
|
4441
|
-
}
|
|
4442
4485
|
if (window.remotion_isMainTab) {
|
|
4443
|
-
Internals17.Log.warn({ logLevel, tag: "@remotion/media" },
|
|
4486
|
+
Internals17.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
|
|
4444
4487
|
}
|
|
4445
4488
|
setReplaceWithOffthreadVideo({
|
|
4446
|
-
durationInSeconds:
|
|
4489
|
+
durationInSeconds: mediaDurationInSeconds
|
|
4447
4490
|
});
|
|
4491
|
+
};
|
|
4492
|
+
if (result.type === "unknown-container-format") {
|
|
4493
|
+
handleError(new Error(`Unknown container format ${src}.`), new Error(`Cannot render video "${src}": Unknown container format. See supported formats: https://www.remotion.dev/docs/mediabunny/formats`), `Unknown container format for ${src} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <OffthreadVideo>`, null);
|
|
4494
|
+
return;
|
|
4495
|
+
}
|
|
4496
|
+
if (result.type === "cannot-decode") {
|
|
4497
|
+
handleError(new Error(`Cannot decode ${src}.`), new Error(`Cannot render video "${src}": The video could not be decoded by the browser.`), `Cannot decode ${src}, falling back to <OffthreadVideo>`, result.durationInSeconds);
|
|
4448
4498
|
return;
|
|
4449
4499
|
}
|
|
4450
4500
|
if (result.type === "cannot-decode-alpha") {
|
|
4451
|
-
|
|
4452
|
-
cancelRender3(new Error(`Cannot render video "${src}": The alpha channel could not be decoded by the browser.`));
|
|
4453
|
-
return;
|
|
4454
|
-
}
|
|
4455
|
-
if (disallowFallbackToOffthreadVideo) {
|
|
4456
|
-
cancelRender3(new Error(`Cannot decode alpha component for ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
|
|
4457
|
-
}
|
|
4458
|
-
if (window.remotion_isMainTab) {
|
|
4459
|
-
Internals17.Log.info({ logLevel, tag: "@remotion/media" }, `Cannot decode alpha component for ${src}, falling back to <OffthreadVideo>`);
|
|
4460
|
-
}
|
|
4461
|
-
setReplaceWithOffthreadVideo({
|
|
4462
|
-
durationInSeconds: result.durationInSeconds
|
|
4463
|
-
});
|
|
4501
|
+
handleError(new Error(`Cannot decode alpha component for ${src}.`), new Error(`Cannot render video "${src}": The alpha channel could not be decoded by the browser.`), `Cannot decode alpha component for ${src}, falling back to <OffthreadVideo>`, result.durationInSeconds);
|
|
4464
4502
|
return;
|
|
4465
4503
|
}
|
|
4466
4504
|
if (result.type === "network-error") {
|
|
4467
|
-
|
|
4468
|
-
cancelRender3(new Error(`Cannot render video "${src}": Network error while fetching the video (possibly CORS).`));
|
|
4469
|
-
return;
|
|
4470
|
-
}
|
|
4471
|
-
if (disallowFallbackToOffthreadVideo) {
|
|
4472
|
-
cancelRender3(new Error(`Cannot decode ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
|
|
4473
|
-
}
|
|
4474
|
-
if (window.remotion_isMainTab) {
|
|
4475
|
-
Internals17.Log.warn({ logLevel, tag: "@remotion/media" }, `Network error fetching ${src} (no CORS?), falling back to <OffthreadVideo>`);
|
|
4476
|
-
}
|
|
4477
|
-
setReplaceWithOffthreadVideo({ durationInSeconds: null });
|
|
4505
|
+
handleError(new Error(`Network error fetching ${src}.`), new Error(`Cannot render video "${src}": Network error while fetching the video (possibly CORS).`), `Network error fetching ${src} (no CORS?), falling back to <OffthreadVideo>`, null);
|
|
4478
4506
|
return;
|
|
4479
4507
|
}
|
|
4480
4508
|
const {
|
|
@@ -4567,7 +4595,8 @@ var VideoForRendering = ({
|
|
|
4567
4595
|
videoEnabled,
|
|
4568
4596
|
maxCacheSize,
|
|
4569
4597
|
cancelRender3,
|
|
4570
|
-
headless
|
|
4598
|
+
headless,
|
|
4599
|
+
onError
|
|
4571
4600
|
]);
|
|
4572
4601
|
const classNameValue = useMemo5(() => {
|
|
4573
4602
|
return [Internals17.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals17.truthy).join(" ");
|
|
@@ -4662,7 +4691,8 @@ var InnerVideo = ({
|
|
|
4662
4691
|
toneFrequency,
|
|
4663
4692
|
showInTimeline,
|
|
4664
4693
|
debugOverlay,
|
|
4665
|
-
headless
|
|
4694
|
+
headless,
|
|
4695
|
+
onError
|
|
4666
4696
|
}) => {
|
|
4667
4697
|
const environment = useRemotionEnvironment4();
|
|
4668
4698
|
if (typeof src !== "string") {
|
|
@@ -4703,7 +4733,8 @@ var InnerVideo = ({
|
|
|
4703
4733
|
toneFrequency,
|
|
4704
4734
|
trimAfterValue,
|
|
4705
4735
|
trimBeforeValue,
|
|
4706
|
-
headless
|
|
4736
|
+
headless,
|
|
4737
|
+
onError
|
|
4707
4738
|
});
|
|
4708
4739
|
}
|
|
4709
4740
|
return /* @__PURE__ */ jsx6(VideoForPreview, {
|
|
@@ -4726,7 +4757,8 @@ var InnerVideo = ({
|
|
|
4726
4757
|
disallowFallbackToOffthreadVideo,
|
|
4727
4758
|
fallbackOffthreadVideoProps,
|
|
4728
4759
|
debugOverlay: debugOverlay ?? false,
|
|
4729
|
-
headless: headless ?? false
|
|
4760
|
+
headless: headless ?? false,
|
|
4761
|
+
onError
|
|
4730
4762
|
});
|
|
4731
4763
|
};
|
|
4732
4764
|
var Video = ({
|
|
@@ -4752,7 +4784,8 @@ var Video = ({
|
|
|
4752
4784
|
stack,
|
|
4753
4785
|
toneFrequency,
|
|
4754
4786
|
debugOverlay,
|
|
4755
|
-
headless
|
|
4787
|
+
headless,
|
|
4788
|
+
onError
|
|
4756
4789
|
}) => {
|
|
4757
4790
|
const fallbackLogLevel = Internals18.useLogLevel();
|
|
4758
4791
|
return /* @__PURE__ */ jsx6(InnerVideo, {
|
|
@@ -4778,7 +4811,8 @@ var Video = ({
|
|
|
4778
4811
|
toneFrequency: toneFrequency ?? 1,
|
|
4779
4812
|
stack,
|
|
4780
4813
|
debugOverlay: debugOverlay ?? false,
|
|
4781
|
-
headless: headless ?? false
|
|
4814
|
+
headless: headless ?? false,
|
|
4815
|
+
onError
|
|
4782
4816
|
});
|
|
4783
4817
|
};
|
|
4784
4818
|
Internals18.addSequenceStackTraces(Video);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type { LogLevel } from 'remotion';
|
|
2
1
|
import type { ExtractFrameViaBroadcastChannelResult } from './video-extraction/extract-frame-via-broadcast-channel';
|
|
3
2
|
export declare const extractFrameAndAudio: ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, loop, audioStreamIndex, trimAfter, trimBefore, fps, maxCacheSize, }: {
|
|
4
3
|
src: string;
|
|
5
4
|
timeInSeconds: number;
|
|
6
|
-
logLevel:
|
|
5
|
+
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
7
6
|
durationInSeconds: number;
|
|
8
7
|
playbackRate: number;
|
|
9
8
|
includeAudio: boolean;
|
package/dist/get-sink.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { LogLevel } from 'remotion';
|
|
2
1
|
import type { GetSink } from './video-extraction/get-frames-since-keyframe';
|
|
3
2
|
export declare const sinkPromises: Record<string, Promise<GetSink>>;
|
|
4
|
-
export declare const getSink: (src: string, logLevel:
|
|
3
|
+
export declare const getSink: (src: string, logLevel: "error" | "info" | "trace" | "verbose" | "warn") => Promise<{
|
|
5
4
|
getVideo: () => Promise<import("./video-extraction/get-frames-since-keyframe").VideoSinkResult>;
|
|
6
5
|
getAudio: (index: number) => Promise<import("./video-extraction/get-frames-since-keyframe").AudioSinkResult>;
|
|
7
6
|
actualMatroskaTimestamps: {
|
package/dist/index.d.ts
CHANGED
|
@@ -10,5 +10,6 @@ export declare const experimental_Audio: import("react").FC<import(".").AudioPro
|
|
|
10
10
|
export declare const experimental_Video: import("react").FC<import(".").VideoProps>;
|
|
11
11
|
export { AudioForPreview } from './audio/audio-for-preview';
|
|
12
12
|
export { AudioProps, FallbackHtml5AudioProps } from './audio/props';
|
|
13
|
-
export {
|
|
13
|
+
export { MediaErrorAction } from './on-error';
|
|
14
|
+
export { FallbackOffthreadVideoProps, VideoProps } from './video/props';
|
|
14
15
|
export { Audio, Video };
|
package/dist/media-player.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export declare class MediaPlayer {
|
|
|
42
42
|
private isPremounting;
|
|
43
43
|
private isPostmounting;
|
|
44
44
|
private seekPromiseChain;
|
|
45
|
-
constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, onVideoFrameCallback, playing
|
|
45
|
+
constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, onVideoFrameCallback, playing }: {
|
|
46
46
|
canvas: HTMLCanvasElement | OffscreenCanvas | null;
|
|
47
47
|
src: string;
|
|
48
48
|
logLevel: LogLevel;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type MediaErrorEvent = {
|
|
2
|
+
error: Error;
|
|
3
|
+
};
|
|
4
|
+
export type MediaErrorAction = 'fallback' | 'fail';
|
|
5
|
+
export type MediaOnError = (error: Error) => MediaErrorAction | undefined;
|
|
6
|
+
export declare const callOnErrorAndResolve: ({ onError, error, disallowFallback, isClientSideRendering, clientSideError, }: {
|
|
7
|
+
onError: MediaOnError | undefined;
|
|
8
|
+
error: Error;
|
|
9
|
+
clientSideError: Error;
|
|
10
|
+
disallowFallback: boolean;
|
|
11
|
+
isClientSideRendering: boolean;
|
|
12
|
+
}) => [MediaErrorAction, Error];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LoopDisplay } from 'remotion';
|
|
2
2
|
export declare const useLoopDisplay: ({ loop, mediaDurationInSeconds, playbackRate, trimAfter, trimBefore, }: {
|
|
3
3
|
loop: boolean;
|
|
4
4
|
mediaDurationInSeconds: number | null;
|
|
5
5
|
trimAfter: number | undefined;
|
|
6
6
|
trimBefore: number | undefined;
|
|
7
7
|
playbackRate: number;
|
|
8
|
-
}) =>
|
|
8
|
+
}) => LoopDisplay | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LoopDisplay } from 'remotion';
|
|
2
2
|
import { type VolumeProp } from 'remotion';
|
|
3
3
|
export declare const useMediaInTimeline: ({ volume, mediaVolume, src, mediaType, playbackRate, displayName, stack, showInTimeline, premountDisplay, postmountDisplay, loopDisplay, trimBefore, trimAfter, }: {
|
|
4
4
|
volume: VolumeProp | undefined;
|
|
@@ -11,7 +11,7 @@ export declare const useMediaInTimeline: ({ volume, mediaVolume, src, mediaType,
|
|
|
11
11
|
showInTimeline: boolean;
|
|
12
12
|
premountDisplay: number | null;
|
|
13
13
|
postmountDisplay: number | null;
|
|
14
|
-
loopDisplay:
|
|
14
|
+
loopDisplay: LoopDisplay | undefined;
|
|
15
15
|
trimBefore: number | undefined;
|
|
16
16
|
trimAfter: number | undefined;
|
|
17
17
|
}) => {
|