У меня есть элемент видео, у которого есть ссылка, которую можно использовать для получения его свойств. По-моему, довольно стандартная вещь. Проблема в том, что при запуске эффекта элемент видео (в videoRef.current) регистрируется и имеет свойство продолжительности, равное 311, но под ним, где я пытаюсь зарегистрировать само свойство продолжительности, не работает. Он регистрирует NaN.
Вот код, соответствующий вопросу.
const Home = () => {
const [videoState, setVideoState] = useState({
playing: false,
currentTime: 0,
volume: "50%",
playbackSpeed: 1,
totalTime: 0,
})
const videoRef = useRef<HTMLVideoElement>(null)
useEffect(() => {
if (videoRef.current) {
console.dir(videoRef.current)
console.info(+videoRef.current.duration)
// console.info(typeof(videoRef.current.duration))
// @ts-ignore
setVideoState((prev) => ({ ...prev, totalTime: videoRef.current.duration }))
}
}, [])
return (
<div className='p-8 bg-red-500 w-full h-full relative'>
<div className='relative w-fit h-fit'>
<video
src = {fall}
ref = {videoRef}
// onPlaying = {handleTimeUpdate}
onTimeUpdate = {handleTimeUpdate}
></video>
</div>
)
}
export default Home
выход
и в видеообъекте есть цифра продолжительности
Я не понимаю, почему продолжительность видеообъекта равна 311 при выходе из системы, но это NaN, когда он регистрируется напрямую.
Я ожидал, что во втором журнале будут записаны данные о продолжительности.
У элемента video нет свойства video. Даже с console.info(+videoRef.current.duration) там всё равно написано NaN





Вы можете посмотреть этот вопрос => Получение продолжительности видео HTML5 отдельно от файла
Проблема в том, что свойство продолжительности доступно после загрузки метаданных. Вам нужно подождать этого.
попробуйте использовать этот useEffect
useEffect(() => {
const handleDurationChange = () => {
if (videoRef.current) {
console.dir(videoRef.current);
console.info(videoRef.current.duration);
setVideoState((prev) => ({ ...prev, totalTime: videoRef.current.duration }));
}
};
if (videoRef.current) {
videoRef.current.addEventListener('durationchange', handleDurationChange);
}
return () => {
if (videoRef.current) {
videoRef.current.removeEventListener('durationchange', handleDurationChange);
}
};
}, []);
Чтобы понять, вы можете скопировать/вставить этот фрагмент в консоль браузера:
const obj = { a: 1, b: 2 };
console.dir(obj); // => you will see { a: 3, b: 2 } in the browser
console.dir({ ...obj }); // => you will see { a: 1, b: 2 } in the browser
obj.a = 3;
когда вы передаете объект напрямую, браузер сохраняет ссылку на него, и если он изменится, он отобразит мутированный объект (с новым состоянием)
Если вы хотите «захватить» состояние console.dir на момент, вам необходимо передать копию объекта.
Это сработало, спасибо. Я до сих пор не понимаю, почему длительность была действительна, когда видеообъект был открыт в консоли браузера, но NaN при регистрации из кода.
Добавляю еще пояснения, подскажите, если непонятно.
Думаю, я понял. Итак, в моем случае браузер хранит videoRef.current в памяти и обновляет его значения при загрузке метаданных. Но доступ только к продолжительности из videoRef.current создает отдельную переменную?
Объект тот же. Когда вы используете console.info(videoRef.current.duration), продолжительность видео еще недоступна, поэтому она отображается как NaN. Когда вы вручную открываете объект в браузере, проходит некоторое время, позволяющее загрузить метаданные. Затем объект мутирует в течение доступной продолжительности.
Это все объясняет. Спасибо, что нашли время объяснить мне это. Я очень благодарен!
Я думаю, вы пропустили «видео». правильно должно быть console.info(+videoRef.current.video.duration)