我希望使用自定义控件来触发自定义按钮上的.play()方法来播放音频文件。澄清一下,我并不是想让音频自动播放。在Chrome中一切工作完美,但在Safari中我得到错误:
未处理的承诺拒绝:NotAllowedError:请求不是在当前上下文中由用户代理或平台允许,可能是因为用户拒绝了权限。
该项目是使用React和React路由器构建的,所以我想知道它是否可能在我的useEffect()钩子中修复。我试过在audio元素上启用控件,并使用CSS将它们从DOM中移除,但没有成功。
import React, { useState, useRef, useEffect } from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { gsap } from "gsap";
function RadioPlayerNav(props) {
const audioEl = useRef(null);
const [isPlaying, setIsPlaying] = useState(false);
const playingTitle = document.querySelector(".radio-player-nav .title p");
const toPX = (value) => {
return (parseFloat(value) / 100) * (/vh/gi.test(value) ? window.innerHeight : window.innerWidth);
};
const radioPlayerGSAP = gsap.to(".radio-player-nav .title p", {
x: toPX("-5vw"),
duration: 4,
ease: "none",
yoyo: true,
repeat: -1,
delay: 1,
repeatDelay: 1,
paused: true,
});
useEffect(() => {
if (isPlaying) {
audioEl.current.play();
radioPlayerGSAP.play();
// radioPlayerGSAP.reversed(4, false);
} else {
audioEl.current.pause();
}
}, [isPlaying]);
return (
<div className="radio-player-nav">
<div className="radio-player-controls">
<audio src="src/current-radio-mix.mp3" ref={audioEl} preload="auto"></audio>
<i
className={isPlaying ? "fas fa-pause cursor-hover" : "fas fa-play cursor-hover"}
onClick={() => {
setIsPlaying(!isPlaying);
}}
></i>
<div className="title">
<p>MIXED FEELINGS M0001</p>
</div>
<a href="src/current-radio-mix.mp3" download="Mixed Feelings M0001">
<i className="fas fa-download cursor-hover"></i>
</a>
</div>
</div>
);
}
export default RadioPlayerNav;
你可以在这里找到项目的完整github repo: https://github.com/nallstott/mixed-feelings/tree/master
结果是,safari要求您使用uselayouteeffect而不是使用use effect来完成此操作。我离开这篇文章,因为我之前没有看到任何给出答案的文章,以及为我解决这个问题的文章,以防其他人在safari上有<audio>
的这个问题。
https://lukecod.es/2020/08/27/ios-cant-play-youtube-via-react-useeffect/
我也在我的应用程序中播放音频,它循环播放它们。我可以通过将音频文件放在地图中,并使用单独的函数来调用音频播放来解决这个问题。
import hold_female from '../../assets/audio/Female/hold_female.mp3';
import exhale_female from '../../assets/audio/Female/exhale_female.mp3';
import inhale_female from '../../assets/audio/Female/inhale_female.mp3';
import hold_male from '../../assets/audio/Male/hold_male.mp3';
import exhale_male from '../../assets/audio/Male/exhale_male.mp3';
import inhale_male from '../../assets/audio/Male/inhale_male.mp3';
//Props here...
createAudio('Exhale_female', exhale_female); //These place the audio into a map under the name provided.
createAudio('Inhale_female', inhale_female);
createAudio('Hold_female', hold_female);
createAudio('Exhale_male', exhale_male);
createAudio('Inhale_male', inhale_male);
createAudio('Hold_male', hold_male);
const BreatheTest: FC<BreathingProps> = ({ gender }) => {
const [stageText, setStageText] = useState<string>('Inhale');
const [index, setIndex] = useState<number>(0);
const [milliseconds, setMilliseconds] = useState<number>(0); //Set to 0 so the audio plays right away and there is no delay.
const captions = ['Inhale', 'Hold', 'Exhale', 'Hold'];
const playAudioFiles = () => {
playAudio(`${stageText}_${gender}`);
};
useEffect(() => {
const timeout = setTimeout(() => {
stopAll(); //stop all the previous audio files if they are running.
setStageText(captions[index]);
setIndex(index === 3 ? 0 : index + 1);
setMilliseconds(isSafari ? 4500 : 4350);//Sets the timeout to the time of the audio files.
playAudioFiles(); //Plays the audio files as the useEffect runs
}, milliseconds);
return () => clearTimeout(timeout);
}, [index]);
//... render method and everything else.
}
我的应用程序是用于控制呼吸,这就是我如何过去你所看到的错误。据我所知,iOS只需要某种触发器来启动任何媒体、音频或视频。将播放函数放入一系列播放函数中,这有点满足Safari。
它可能不适合你,或者你的代码如何工作,但如果这是我们可以讨论如何绕过iOS的音频控制,这是另一种方式。