英文:
Play same audio twice, then move to the next audio file in React
问题
我正在尝试从一个数组中自动播放音频文件,使用 react-audio-player。我想要每个音频播放两次,然后自动切换到下一个。
我找到了一种自动播放所有音频的方法,但是当我想要再次播放同一音频时,播放器停止。因此,它播放第一个音频,停止,然后我再次点击播放,它再次播放第一个音频并切换到第二个,然后再次停止。
我认为问题在于音频的 URL 没有更改,播放器不将其识别为新音频。
我几乎找不到与此问题相关的帖子,因为这是相当特定的问题。我将感激任何帮助。
const userItems = [
{ "MP3": "https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav" },
{ "MP3": "https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav" },
{ "MP3": "https://www2.cs.uic.edu/~i101/SoundFiles/Fanfare60.wav" }
]
const [repeatAudio, setRepeatAudio] = useState(true); // 确定音频是否已经播放过
const [currentAudioIndex, setCurrentAudioIndex] = useState(0);
const audioSrc = userItems[currentAudioIndex].MP3
function setNextAudio() {
if (repeatAudio) { // 如果音频还没有播放,保持相同的音频索引
setCurrentAudioIndex(i => i + 0)
setRepeatAudio(false)
} else { // 如果已经播放过,跳到下一个索引
setCurrentAudioIndex(i => i + 1)
setRepeatAudio(true)
}
}
return (
<div>
<ReactAudioPlayer
src={audioSrc}
autoPlay
controls
onEnded={() => setNextAudio()}
/>
</div>
)
希望这有所帮助。
英文:
I'm trying to make an autoplay of audio files from an array, using the react-audio-player. I want to play each audio twice, and then automatically move to the next one.
I found a way to automatically play all the audios, but when I want to play the same audio second time, the player stops. So it plays the first audio, stops, then I click play again and it plays the first audio again and advances to the second, and then stops again.
I think the problem is that since the audio URL doesn't change, the player doesn't recognize it as a new audio.
I can't find almost any threads related to this issue, as it's quite specific. I will appreciate any help.
const userItems = [{ "MP3": "https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav" }, { "MP3": "https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav" }, { "MP3": "https://www2.cs.uic.edu/~i101/SoundFiles/Fanfare60.wav" }]
const [repeatAudio, setRepeatAudio] = useState(true); // Determine if the audio has been played already
const [currentAudioIndex, setCurrentAudioIndex] = useState(0);
const audioSrc = userItems[currentAudioIndex].MP3
function setNextAudio() {
if (repeatAudio) { // If the audio hasn't been played, keep same audio index
setCurrentAudioIndex(i => i + 0)
setRepeatAudio(false)
} else { // If it has been played, jump to the next index
setCurrentAudioIndex(i => i + 1)
setRepeatAudio(true)
}
}
return (
<div>
<ReactAudioPlayer
src={audioSrc}
autoPlay
controls
onEnded={() => setNextAudio()}
/>
</div>
)
}
答案1
得分: 1
我已经稍微整理了一下,以使其更容易理解,但是关键部分是“replay”不涉及URL更改,因此autoPlay
不会生效。您必须通过获取音频元素的引用并直接操纵它来自行管理。
import React, { useState, useRef } from "react";
import ReactAudioPlayer from "react-audio-player";
const userItems = [
{ MP3: "https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav" },
{ MP3: "https://www2.cs.uic.edu/~i101/SoundFiles/Fanfare60.wav" }
];
const PlayTwicePlayer = () => {
const [audioPointer, setAudioPointer] = useState({
index: 0,
playedOnce: false
});
const audioPlayerRef = useRef(null);
const audioSrc = userItems[audioPointer.index].MP3;
function handleAudioEnded() {
// 如果已经在数组的末尾,请不要继续下一首曲目
if (audioPointer.index >= userItems.length - 1) return;
if (audioPointer.playedOnce) {
// 如果已经播放过它,那么我们刚刚完成了第二次播放,需要转到下一首曲目。
setAudioPointer((prev) => ({
index: prev.index + 1,
playedOnce: false
}));
return;
} else {
// 如果他们尚未播放过它,我们刚刚完成了第一次运行,现在可以将playedOnce设置为true。
// 我们还必须通过引用到播放器来手动将其重定位到0并播放,因为autoPlay不会触发,因为URL没有更改。
setAudioPointer((prev) => ({ ...prev, playedOnce: true }));
audioPlayerRef.current.currentTime = 0;
audioPlayerRef.current.play();
return;
}
}
return (
<div>
<ReactAudioPlayer
src={audioSrc}
autoPlay
controls
onEnded={handleAudioEnded}
ref={(ref) => {
if (!ref) return;
audioPlayerRef.current = ref.audioEl.current;
}}
/>
</div>
);
};
请注意,这不会给您无缝的过渡。要实现无缝过渡,您需要使用WebAudio API。有易于使用的库包装器,例如 https://github.com/t-mullen/video-stream-merger 和 https://github.com/jaggad/crunker。
英文:
I've cleaned this up a bit to make it easier to understand, but yes the key bit is the "replay" doesn't involve a URL change, and so autoPlay
doesn't kick in. You have to manage that yourself by getting a reference to the audio element and prodding it directly.
import React, { useState, useRef } from "react";
import ReactAudioPlayer from "react-audio-player";
const userItems = [
{ MP3: "https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav" },
{ MP3: "https://www2.cs.uic.edu/~i101/SoundFiles/Fanfare60.wav" }
];
const PlayTwicePlayer = () => {
const [audioPointer, setAudioPointer] = useState({
index: 0,
playedOnce: false
});
const audioPlayerRef = useRef(null);
const audioSrc = userItems[audioPointer.index].MP3;
function handleAudioEnded() {
// Dont proceed to next track if already at the end of the array
if (audioPointer.index >= userItems.length - 1) return;
if (audioPointer.playedOnce) {
// If they already played it, that means we just finished playing it a second time, and need to move to the next track.
setAudioPointer((prev) => ({
index: prev.index + 1,
playedOnce: false
}));
return;
} else {
// If they hadn't already played it, we just finished the first run so we can set playedOnce to true now.
// We must additionally seek back to 0 and play manually using a reference to the player because autoPlay does not
// trigger since the URL didn't change.
setAudioPointer((prev) => ({ ...prev, playedOnce: true }));
audioPlayerRef.current.currentTime = 0;
audioPlayerRef.current.play();
return;
}
}
return (
<div>
<ReactAudioPlayer
src={audioSrc}
autoPlay
controls
onEnded={handleAudioEnded}
ref={(ref) => {
if (!ref) return;
audioPlayerRef.current = ref.audioEl.current;
}}
/>
</div>
);
};
Note this won't give you seamless transitions. To do that you'd need the WebAudio API. Easy library wrappers for it exist like https://github.com/t-mullen/video-stream-merger and https://github.com/jaggad/crunker.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论