可以在Safari中的iOS上播放视频:NotalloedError:在当前上下文中,用户代理不允许请求
当我在Safari中单击iPhone上的播放按钮时,我会收到以下错误:
NotallowedError:用户代理或当前上下文中平台不允许请求,这可能是因为用户拒绝许可。
我在Internet上进行了搜索,似乎这个问题已经存在很长时间了,但是没有明确的解决方案。
这是我的代码。除ios Safari以外,它在任何地方都可以使用。
import { Box } from '@chakra-ui/react';
import { useTranslation } from 'libs/i18next';
import React, { useEffect, useRef, useState } from 'react';
import { PauseIcon, PlayIcon } from 'theme/icons';
import { visuallyHiddenCss } from 'utils/style-utils';
import {
buttonHoverArea,
playButtonCss,
playIconStyles,
videoContainerCss,
videoCss,
} from './Video.styles';
export interface Video extends React.HTMLProps<HTMLVideoElement> {
src: string;
noVideoText?: string;
className?: string;
isEnabled?: boolean;
coversParent?: boolean;
handlePlayPress?: (videoPlaying: boolean) => void;
}
/**
* Default HTML5 video player with a play button and a preview thumbnail image.
*/
export const Video = ({
src,
noVideoText,
className,
loop = false,
autoPlay = false, // AutoPlay doesn't work currently
isEnabled = true,
coversParent = false,
handlePlayPress,
...props
}: Video): React.ReactElement => {
const [t] = useTranslation(['common']);
const videoRef = useRef<HTMLVideoElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
// use videoStarted state to hide the play button once it has been started
const [videoPlaying, setVideoPlaying] = useState<boolean>(false);
const pauseVideo = () => {
setVideoPlaying(false);
};
const toggleVideo = () => {
if (handlePlayPress) {
handlePlayPress(!videoPlaying);
}
setVideoPlaying(!videoPlaying);
};
const defaultProps: Partial<Video> = {
width: '100%',
height: '100%',
preload: 'none',
onClick: pauseVideo,
tabIndex: -1,
};
const videoProps = Object.assign(defaultProps, props);
useEffect(() => {
if (videoRef.current && props.muted) {
// force muted prop
// https://github.com/facebook/react/issues/10389#issuecomment-605689475
videoRef.current.setAttribute('muted', '');
videoRef.current.defaultMuted = true;
}
}, [props.muted, videoRef]);
useEffect(() => {
if (isEnabled && videoPlaying) {
videoRef.current?.play();
buttonRef.current?.blur();
videoRef.current?.focus();
} else {
videoRef.current?.pause();
}
}, [isEnabled, videoPlaying, videoRef]);
const PlayPauseIcon = videoPlaying ? PauseIcon : PlayIcon;
return (
<Box
css={[
videoContainerCss.base,
coversParent ? videoContainerCss.cover : undefined,
]}
className={className}
>
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
<video
ref={videoRef}
css={videoCss}
{...videoProps}
autoPlay={autoPlay}
loop={loop}
>
<source src={src} type={'video/mp4'} />
{noVideoText}
</video>
{isEnabled && (
<div
css={[buttonHoverArea.base, videoPlaying && buttonHoverArea.playing]}
>
<button
type="button"
ref={buttonRef}
css={playButtonCss}
onClick={toggleVideo}
// prevent hidden elements from being focused
>
<span css={visuallyHiddenCss}>
{videoPlaying ? t('common:video.pause') : t('common:video.play')}
</span>
<PlayPauseIcon
css={!videoPlaying && playIconStyles}
boxSize={'6rem'}
aria-hidden
/>
</button>
</div>
)}
</Box>
);
};
如何避免此错误?为什么会发生?
When I click a play button on an iPhone in Safari, I get the following error:
NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
I searched on the internet and it seems that this issue has been around for a long time but there is no clear solution to it.
Here is my code. It works everywhere except iOS Safari.
import { Box } from '@chakra-ui/react';
import { useTranslation } from 'libs/i18next';
import React, { useEffect, useRef, useState } from 'react';
import { PauseIcon, PlayIcon } from 'theme/icons';
import { visuallyHiddenCss } from 'utils/style-utils';
import {
buttonHoverArea,
playButtonCss,
playIconStyles,
videoContainerCss,
videoCss,
} from './Video.styles';
export interface Video extends React.HTMLProps<HTMLVideoElement> {
src: string;
noVideoText?: string;
className?: string;
isEnabled?: boolean;
coversParent?: boolean;
handlePlayPress?: (videoPlaying: boolean) => void;
}
/**
* Default HTML5 video player with a play button and a preview thumbnail image.
*/
export const Video = ({
src,
noVideoText,
className,
loop = false,
autoPlay = false, // AutoPlay doesn't work currently
isEnabled = true,
coversParent = false,
handlePlayPress,
...props
}: Video): React.ReactElement => {
const [t] = useTranslation(['common']);
const videoRef = useRef<HTMLVideoElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
// use videoStarted state to hide the play button once it has been started
const [videoPlaying, setVideoPlaying] = useState<boolean>(false);
const pauseVideo = () => {
setVideoPlaying(false);
};
const toggleVideo = () => {
if (handlePlayPress) {
handlePlayPress(!videoPlaying);
}
setVideoPlaying(!videoPlaying);
};
const defaultProps: Partial<Video> = {
width: '100%',
height: '100%',
preload: 'none',
onClick: pauseVideo,
tabIndex: -1,
};
const videoProps = Object.assign(defaultProps, props);
useEffect(() => {
if (videoRef.current && props.muted) {
// force muted prop
// https://github.com/facebook/react/issues/10389#issuecomment-605689475
videoRef.current.setAttribute('muted', '');
videoRef.current.defaultMuted = true;
}
}, [props.muted, videoRef]);
useEffect(() => {
if (isEnabled && videoPlaying) {
videoRef.current?.play();
buttonRef.current?.blur();
videoRef.current?.focus();
} else {
videoRef.current?.pause();
}
}, [isEnabled, videoPlaying, videoRef]);
const PlayPauseIcon = videoPlaying ? PauseIcon : PlayIcon;
return (
<Box
css={[
videoContainerCss.base,
coversParent ? videoContainerCss.cover : undefined,
]}
className={className}
>
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
<video
ref={videoRef}
css={videoCss}
{...videoProps}
autoPlay={autoPlay}
loop={loop}
>
<source src={src} type={'video/mp4'} />
{noVideoText}
</video>
{isEnabled && (
<div
css={[buttonHoverArea.base, videoPlaying && buttonHoverArea.playing]}
>
<button
type="button"
ref={buttonRef}
css={playButtonCss}
onClick={toggleVideo}
// prevent hidden elements from being focused
>
<span css={visuallyHiddenCss}>
{videoPlaying ? t('common:video.pause') : t('common:video.play')}
</span>
<PlayPauseIcon
css={!videoPlaying && playIconStyles}
boxSize={'6rem'}
aria-hidden
/>
</button>
</div>
)}
</Box>
);
};
How can I avoid this error? And why is it happening?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要在视频上设置
PlayaySinline
才能使其在iPhone上工作。例如,在
videoref.current.setAttribute('muted',''');
::::You need to set the
playsinline
on video to be true for it to work on iPhone.e.g. add below line after
videoRef.current.setAttribute('muted', '');
:解决方案是将静态属性添加到将传递到视频的组件中。不幸的是,这导致视频被静音。就我而言,我拥有
&lt; homepage /&gt; < /code>组件,然后将其传递给
&lt; video /&gt; < /code> component。
可能的解决方案:添加控制器或将声音绑定到播放按钮上(后者可能不是最好的)。
The solution was to add muted property to the component which will be passed down to the video. Unfortunately it resulted in video being muted. In my case, I had
<HomePage />
component and I passed muted down to the<Video />
component.Possible solutions: add controllers or bind sound onto the play button (the latter might be not the best one).