remotion
Version:
Make videos programmatically
89 lines (88 loc) • 3.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useVolume = void 0;
const react_1 = require("react");
const shared_audio_tags_1 = require("./audio/shared-audio-tags");
const is_approximately_the_same_1 = require("./is-approximately-the-same");
const log_1 = require("./log");
const video_fragment_1 = require("./video/video-fragment");
let warned = false;
const warnSafariOnce = (logLevel) => {
if (warned) {
return;
}
warned = true;
log_1.Log.warn(logLevel, 'In Safari, setting a volume and a playback rate at the same time is buggy.');
log_1.Log.warn(logLevel, 'In Desktop Safari, only volumes <= 1 will be applied.');
log_1.Log.warn(logLevel, 'In Mobile Safari, the volume will be ignored and set to 1 if a playbackRate is set.');
};
/**
* [1] Bug case: In Safari, you cannot combine playbackRate and volume !== 1.
* If that is the case, volume will not be applied.
*/
const useVolume = ({ mediaRef, volume, logLevel, source, shouldUseWebAudioApi, }) => {
var _a, _b, _c;
const audioStuffRef = (0, react_1.useRef)(null);
const currentVolumeRef = (0, react_1.useRef)(volume);
currentVolumeRef.current = volume;
const sharedAudioContext = (0, react_1.useContext)(shared_audio_tags_1.SharedAudioContext);
if (!sharedAudioContext) {
throw new Error('useAmplification must be used within a SharedAudioContext');
}
const { audioContext } = sharedAudioContext;
if (typeof window !== 'undefined') {
// eslint-disable-next-line react-hooks/rules-of-hooks
(0, react_1.useLayoutEffect)(() => {
var _a, _b;
if (!audioContext) {
return;
}
if (!mediaRef.current) {
return;
}
if (!shouldUseWebAudioApi) {
return;
}
// [1]
if (mediaRef.current.playbackRate !== 1 && (0, video_fragment_1.isSafari)()) {
warnSafariOnce(logLevel);
return;
}
if (!source) {
return;
}
const gainNode = new GainNode(audioContext, {
gain: currentVolumeRef.current,
});
source.attemptToConnect();
source.get().connect(gainNode);
gainNode.connect(audioContext.destination);
audioStuffRef.current = {
gainNode,
};
log_1.Log.trace(logLevel, `Starting to amplify ${(_a = mediaRef.current) === null || _a === void 0 ? void 0 : _a.src}. Gain = ${currentVolumeRef.current}, playbackRate = ${(_b = mediaRef.current) === null || _b === void 0 ? void 0 : _b.playbackRate}`);
return () => {
audioStuffRef.current = null;
gainNode.disconnect();
source.get().disconnect();
};
}, [logLevel, mediaRef, audioContext, source, shouldUseWebAudioApi]);
}
if (audioStuffRef.current) {
const valueToSet = volume;
if (!(0, is_approximately_the_same_1.isApproximatelyTheSame)(audioStuffRef.current.gainNode.gain.value, valueToSet)) {
audioStuffRef.current.gainNode.gain.value = valueToSet;
log_1.Log.trace(logLevel, `Setting gain to ${valueToSet} for ${(_a = mediaRef.current) === null || _a === void 0 ? void 0 : _a.src}`);
}
}
const safariCase = (0, video_fragment_1.isSafari)() && mediaRef.current && ((_b = mediaRef.current) === null || _b === void 0 ? void 0 : _b.playbackRate) !== 1;
const shouldUseTraditionalVolume = safariCase || !shouldUseWebAudioApi;
// [1]
if (shouldUseTraditionalVolume &&
mediaRef.current &&
!(0, is_approximately_the_same_1.isApproximatelyTheSame)(volume, (_c = mediaRef.current) === null || _c === void 0 ? void 0 : _c.volume)) {
mediaRef.current.volume = Math.min(volume, 1);
}
return audioStuffRef;
};
exports.useVolume = useVolume;