播放相同的音频两次,然后在React中切换到下一个音频文件。

huangapple go评论51阅读模式
英文:

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 = [{ &quot;MP3&quot;: &quot;https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav&quot; }, { &quot;MP3&quot;: &quot;https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav&quot; }, { &quot;MP3&quot;: &quot;https://www2.cs.uic.edu/~i101/SoundFiles/Fanfare60.wav&quot; }]

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&#39;t been played, keep same audio index
        setCurrentAudioIndex(i =&gt; i + 0)
        setRepeatAudio(false) 
    } else { // If it has been played, jump to the next index
        setCurrentAudioIndex(i =&gt; i + 1)
        setRepeatAudio(true)
    }
}

return (
    &lt;div&gt;
        &lt;ReactAudioPlayer
            src={audioSrc}
            autoPlay
            controls
            onEnded={() =&gt; setNextAudio()}
        /&gt;
    &lt;/div&gt;
)

}

答案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-mergerhttps://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 &quot;react&quot;;
import ReactAudioPlayer from &quot;react-audio-player&quot;;
const userItems = [
{ MP3: &quot;https://www2.cs.uic.edu/~i101/SoundFiles/CantinaBand3.wav&quot; },
{ MP3: &quot;https://www2.cs.uic.edu/~i101/SoundFiles/Fanfare60.wav&quot; }
];
const PlayTwicePlayer = () =&gt; {
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 &gt;= 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) =&gt; ({
index: prev.index + 1,
playedOnce: false
}));
return;
} else {
// If they hadn&#39;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&#39;t change.
setAudioPointer((prev) =&gt; ({ ...prev, playedOnce: true }));
audioPlayerRef.current.currentTime = 0;
audioPlayerRef.current.play();
return;
}
}
return (
&lt;div&gt;
&lt;ReactAudioPlayer
src={audioSrc}
autoPlay
controls
onEnded={handleAudioEnded}
ref={(ref) =&gt; {
if (!ref) return;
audioPlayerRef.current = ref.audioEl.current;
}}
/&gt;
&lt;/div&gt;
);
};

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.

huangapple
  • 本文由 发表于 2023年6月2日 04:31:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76385512.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定