UNPKG

6.23 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.VideoForRendering = void 0;
4const jsx_runtime_1 = require("react/jsx-runtime");
5const react_1 = require("react");
6const absolute_src_1 = require("../absolute-src");
7const use_audio_frame_1 = require("../audio/use-audio-frame");
8const CompositionManager_1 = require("../CompositionManager");
9const is_approximately_the_same_1 = require("../is-approximately-the-same");
10const is_remote_asset_1 = require("../is-remote-asset");
11const random_1 = require("../random");
12const ready_manager_1 = require("../ready-manager");
13const sequencing_1 = require("../sequencing");
14const use_frame_1 = require("../use-frame");
15const use_unsafe_video_config_1 = require("../use-unsafe-video-config");
16const volume_prop_1 = require("../volume-prop");
17const get_current_time_1 = require("./get-current-time");
18const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, playbackRate, ...props }, ref) => {
19 const absoluteFrame = (0, use_frame_1.useAbsoluteCurrentFrame)();
20 const frame = (0, use_frame_1.useCurrentFrame)();
21 const volumePropsFrame = (0, use_audio_frame_1.useFrameForVolumeProp)();
22 const videoConfig = (0, use_unsafe_video_config_1.useUnsafeVideoConfig)();
23 const videoRef = (0, react_1.useRef)(null);
24 const sequenceContext = (0, react_1.useContext)(sequencing_1.SequenceContext);
25 const mediaStartsAt = (0, use_audio_frame_1.useMediaStartsAt)();
26 const { registerAsset, unregisterAsset } = (0, react_1.useContext)(CompositionManager_1.CompositionManager);
27 // Generate a string that's as unique as possible for this asset
28 // but at the same time the same on all threads
29 const id = (0, react_1.useMemo)(() => {
30 var _a;
31 return `video-${(0, random_1.random)((_a = props.src) !== null && _a !== void 0 ? _a : '')}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom}-${sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames}-muted:${props.muted}`;
32 }, [
33 props.src,
34 props.muted,
35 sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.cumulatedFrom,
36 sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.relativeFrom,
37 sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.durationInFrames,
38 ]);
39 if (!videoConfig) {
40 throw new Error('No video config found');
41 }
42 const volume = (0, volume_prop_1.evaluateVolume)({
43 volume: volumeProp,
44 frame: volumePropsFrame,
45 mediaVolume: 1,
46 });
47 (0, react_1.useEffect)(() => {
48 if (!props.src) {
49 throw new Error('No src passed');
50 }
51 if (props.muted) {
52 return;
53 }
54 registerAsset({
55 type: 'video',
56 src: (0, absolute_src_1.getAbsoluteSrc)(props.src),
57 id,
58 frame: absoluteFrame,
59 volume,
60 isRemote: (0, is_remote_asset_1.isRemoteAsset)((0, absolute_src_1.getAbsoluteSrc)(props.src), false),
61 mediaFrame: frame,
62 playbackRate: playbackRate !== null && playbackRate !== void 0 ? playbackRate : 1,
63 });
64 return () => unregisterAsset(id);
65 }, [
66 props.muted,
67 props.src,
68 registerAsset,
69 id,
70 unregisterAsset,
71 volume,
72 frame,
73 absoluteFrame,
74 playbackRate,
75 ]);
76 (0, react_1.useImperativeHandle)(ref, () => {
77 return videoRef.current;
78 });
79 (0, react_1.useEffect)(() => {
80 if (!videoRef.current) {
81 return;
82 }
83 const currentTime = (() => {
84 return (0, get_current_time_1.getMediaTime)({
85 fps: videoConfig.fps,
86 frame,
87 src: props.src,
88 playbackRate: playbackRate || 1,
89 startFrom: -mediaStartsAt,
90 });
91 })();
92 const handle = (0, ready_manager_1.delayRender)();
93 if (process.env.NODE_ENV === 'test') {
94 (0, ready_manager_1.continueRender)(handle);
95 return;
96 }
97 if ((0, is_approximately_the_same_1.isApproximatelyTheSame)(videoRef.current.currentTime, currentTime)) {
98 if (videoRef.current.readyState >= 2) {
99 (0, ready_manager_1.continueRender)(handle);
100 return;
101 }
102 videoRef.current.addEventListener('loadeddata', () => {
103 (0, ready_manager_1.continueRender)(handle);
104 }, { once: true });
105 return;
106 }
107 videoRef.current.currentTime = currentTime;
108 videoRef.current.addEventListener('seeked', () => {
109 if (window.navigator.platform.startsWith('Mac')) {
110 // Improve me: This is ensures frame perfectness but slows down render.
111 // Please see this issue for context: https://github.com/remotion-dev/remotion/issues/200
112 // Only affects macOS since it uses VideoToolbox decoding.
113 setTimeout(() => {
114 (0, ready_manager_1.continueRender)(handle);
115 }, 100);
116 }
117 else {
118 (0, ready_manager_1.continueRender)(handle);
119 }
120 }, { once: true });
121 videoRef.current.addEventListener('ended', () => {
122 (0, ready_manager_1.continueRender)(handle);
123 }, { once: true });
124 videoRef.current.addEventListener('error', (err) => {
125 console.error('Error occurred in video', err);
126 (0, ready_manager_1.continueRender)(handle);
127 }, { once: true });
128 }, [
129 volumePropsFrame,
130 props.src,
131 playbackRate,
132 videoConfig.fps,
133 frame,
134 mediaStartsAt,
135 ]);
136 return (0, jsx_runtime_1.jsx)("video", Object.assign({ ref: videoRef }, props, { onError: onError }), void 0);
137};
138exports.VideoForRendering = (0, react_1.forwardRef)(VideoForRenderingForwardFunction);
139//# sourceMappingURL=VideoForRendering.js.map
\No newline at end of file