当前位置: 首页 > 面试题库 >

如何在React&Redux中处理音频播放

卢子民
2023-03-14
问题内容

我正在制作音频播放器。它具有暂停,倒带和时间搜索功能。如何以及由谁处理音频元素?

  • 我可以把它放在商店旁边。我不能将其直接放在状态上,因为它可能会被克隆。然后,在减速器中,我可以与其进行交互。问题是,如果我需要将时间滑块与音频同步,则需要使用动作不断地轮询商店。从语义上讲,这也没有任何意义。
  • 我可以创建一个自定义的React组件Audio,它可以完成我所说的一切。问题没有解决。如何刷新滑块?我可以投票,但我真的不喜欢这种解决方案。此外,除非我创建一个既包含音频又包含滑块的组件,否则仍然需要使用redux来连接两者。

那么,使用进度显示处理音频的最主要的方法是什么?


问题答案:

Redux-所有关于状态和一致性。

您的目标是使歌曲时间和进度条保持同步。

我看到两个可能的方法:

因此,您必须将歌曲的当前时间(例如,以秒为单位)保存在商店中,因为其中有一些依赖组件,如果没有商店,很难同步它们。

您很少会更改当前时间的事件:

  • 当前时间本身。例如,每1秒。
  • 倒带。
  • 时间寻求。

更改时间后,您将调度操作并使用新时间更新商店。从而保持当前歌曲的时间,所有组件将同步。

使用动作分派,缩减器和存储来管理单向数据流中的状态是实现任何组件的Redux方法。

这是#1方法的伪代码:

class AudioPlayer extends React.Component {

    onPlay(second) {
        // Store song current time in the Store on each one second
        store.dispatch({ type: 'SET_CURRENT_SECOND', second });
    }

    onRewind(seconds) {
        // Rewind song current time
        store.dispatch({ type: 'REWIND_CURRENT_SECOND', seconds });
    }

    onSeek(seconds) {
        // Seek song current time
        store.dispatch({ type: 'SEEK_CURRENT_SECOND', seconds });
    }

    render() {
        const { currentTime, songLength } = this.state;

        return <div>
            <audio onPlay={this.onPlay} onRewind={this.onRewind} onSeek={this.onSeek} />

            <AudioProgressBar currentTime songLength />
        </div>
    }
}

2.尽量减少存放在商店中。

如果上述方法不符合您的需求,例如,您可能在同一屏幕上有很多音频播放器-可能会有性能差距。

在这种情况下,您可以通过componentDidMount生命周期方法中的引用访问HTML5音频标签和组件。

HTML5音频标签具有DOM事件,您可以在不触摸商店的情况下使两个组件保持同步。如果需要在商店中保存某些东西-您可以随时进行。

请查看react-audio-player源代码,并检查其如何处理引用以及插件公开的API。当然,您可以从那里得到启发。您也可以将其重新用于您的用例。

以下是一些与您的问题相关的API方法:

  • onSeeked-在用户将时间指示器拖动到新时间时调用。通过了活动。
  • onPlay-用户点击播放时调用。通过了活动。
  • onPause-在用户暂停播放时调用。通过了活动。
  • onListen-在播放期间每隔listenInterval毫秒调用一次。通过了活动。

我应该使用哪种方法?

这取决于您的用例细节。但是,一般来讲,在这两种方法中,最好使用必要的API方法来实现表示性组件,这取决于您决定在存储中管理多少数据。

因此,我为您创建了一个启动组件,以说明如何处理对音频和滑块的引用。包括开始/停止/搜索功能。当然,它有缺点,但是正如我已经提到的,这是一个很好的起点。

您可以使用适合您需要的API方法将其发展为一个演示组件

class Audio extends React.Component {

    constructor(props) {

        super(props);



        this.state = {

            duration: null

        }

    };



    handlePlay() {

        this.audio.play();

    }



    handleStop() {

        this.audio.currentTime = 0;

        this.slider.value = 0;

        this.audio.pause();

    }



    componentDidMount() {

        this.slider.value = 0;

        this.currentTimeInterval = null;



        // Get duration of the song and set it as max slider value

        this.audio.onloadedmetadata = function() {

            this.setState({duration: this.audio.duration});

        }.bind(this);



        // Sync slider position with song current time

        this.audio.onplay = () => {

            this.currentTimeInterval = setInterval( () => {

                this.slider.value = this.audio.currentTime;

            }, 500);

        };



        this.audio.onpause = () => {

            clearInterval(this.currentTimeInterval);

        };



        // Seek functionality

        this.slider.onchange = (e) => {

            clearInterval(this.currentTimeInterval);

            this.audio.currentTime = e.target.value;

        };

    }



    render() {

        const src = "https://mp3.gisher.org/download/1000/preview/true";





        return <div>

            <audio ref={(audio) => { this.audio = audio }} src={src} />



            <input type="button" value="Play"

                onClick={ this.handlePlay.bind(this) } />



            <input type="button"

                    value="Stop"

                    onClick={ this.handleStop.bind(this) } />



            <p><input ref={(slider) => { this.slider = slider }}

                    type="range"

                    name="points"

                    min="0" max={this.state.duration} /> </p>

        </div>

    }

}



ReactDOM.render(<Audio />, document.getElementById('container'));


<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="container">

    <!-- This element's contents will be replaced with your component. -->

</div>

如果您有任何疑问,请在下面评论!:)



 类似资料:
  • 我正在使用Expo构建一个react原生应用程序。我用的是“EXPO-AV”。 我无法在后台播放我的音频文件。 我有以下的,但仍然不能使它工作,当我切换我的应用程序到另一个应用程序。我没有任何错误;音乐就停在我的应用程序里了。有什么建议可以让它工作吗?或者我的代码可能出了问题?

  • 问一下Xamarin.Forms便携里面Xamarin.Forms的音频怎么播放 正如我所知,有依赖服务,我看到了一些示例,只有iOS和Android,但没有Windows Phone 8.1/Windows 8.1和UWP。

  • 我对javascript和discord.js很陌生,有人知道如何让机器人加入一个频道,播放一个文件然后离开吗? 以下是我尝试过的: 现在,它将发送消息加入语音通道,而不管我是否在其中,如果我在其中,它就不会加入语音通道并播放文件。任何帮助都很感激。

  • 问题内容: 我正在制作一个Java应用程序,我需要播放音频。尽管我计划循环播放背景音乐,但我主要播放的是我的大炮射击(它是大炮射击游戏)和弹丸爆炸的小声音文件。我找到了两种不同的方法来实现此目的,但是两种方法都不符合我的要求。 第一种方法实际上是一种方法: 问题是我的整个程序停止运行,直到声音文件完成或至少接近完成。 第二种方法是这样的: 我这里的问题是,每次声音文件提早结束或根本不播放时,这取决

  • 问题内容: 我收到mp3网址作为api调用的响应。我想播放该音频,那么我该怎么做?(iOS迅速) 这是我的回应 这是我的代码:: 我要去哪里错了? 问题答案: 我尝试了以下方法 添加以下方法, 和您的播放方法一样, 下载mp3文件,然后尝试播放,但AVAudioPlayer无法以某种方式为您下载mp3文件。我可以下载音频文件,然后播放器播放它。 请记住,将其添加到info.plist中,因为您是从

  • 问题内容: 在我的组件中,我具有以下内容: 不调用取消订阅会导致以下错误: 警告:setState(…):只能更新已安装或正在安装的组件。这通常意味着您在未安装的组件上调用了setState()。这是无人值守。 我想知道的是我应该分配给它,还是有更好的分配空间? 问题答案: 正如Salehen Rahman在上面的评论中提到的,我最终还是使用react-redux。 根据他们的文档,我创建了两个函