Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 audio is not playing in my React app in localhost

I'm making an mp3 player with React.js and the HTML5 web audio javascript API. I've just been learning React for two weeks so I'm just getting used to the structure and setup (with components etc) however have several years experience with JavaScript.

I had the mp3 player working when using React within the browser. I.e. I had an index.html file and I included the React scripts as follows:

<script src="js/react.min.js"></script>
<script src="js/react-dom.min.js"></script>
<script src="js/browser.min.js"></script>

Now I would like to get used to building a React app using the command line and localhost so I started to rewrite the code for use within this environment. I started off by creating the skeleton app as follows:

create-react-app my-app
cd my-app/
npm start

Then I added in my own components etc. The application is displaying properly on localhost:3000 however the audio files do not seem to be playing in this environment. I'm unsure if the problem is directly related to the HTML5 audio just not working in localhost or if it's something else. There are no errors being returned.

I've simplified my code and also hard-coded in the directory of the mp3 file to the audio tag (see AudioPlayer component) for the moment in order to see if I can get the audio element working.

Can you see anything I might be missing? Thanks

App Component

    import React, { Component } from 'react';
    import Header from './Header';

    import AudioPlayer from './AudioPlayer';

    import Controls from './Controls';

    import './music-player.css';
    import './css/font-awesome.css';


    class App extends Component {

         //This class is the main component of the application.
         //it contains the header, the audio player and the side panel components.
         constructor(props) {
                super(props);
                this.state = {
                sidePanelIsOpen: false,
                currentSoundIndex: 0,
                isPlaying: false,
                playerDuration: 0,
                currentTime: "0:00",
                currentWidthOfTimerBar: 0,
                backButtonIsDisabled: false,
                forwardButtonIsDisabled: false,
                playButtonIsDisabled: false


            };
            this.toggleSidePanel = this.toggleSidePanel.bind(this);

        }   
        componentDidMount() {
            this.player = document.getElementById('audio_player');
            this.player.load();
            this.player.play(); //this is not doing anything
        }   
        toggleSidePanel(){
            var sidePanelIsOpen = this.state.sidePanelIsOpen;
            this.setState({sidePanelIsOpen: !sidePanelIsOpen})
        }


        render() {


            return(<div>
                <div id="main-container" className={this.state.sidePanelIsOpen === true ? 'swipe-left' : ''}>
                <div className="overlay">

                <AudioPlayer sounds={this.props.sounds} currentSoundIndex={this.state.currentSoundIndex} />
                </div>  
                </div>


                <div id="side-panel-area" className="scrollable">       
                    <div className="side-panel-container">
                    <div className="side-panel-header"><p>Menu</p></div>

                    </div>
                </div>
                </div>
            );  
        }

    }

    export default App;

AudioPlayer Component

    import React, { Component } from 'react';
    import './music-player.css';

    const AudioPlayer = function(props) {
        var mp3Src = props.sounds[props.currentSoundIndex].mp3;
        console.log(mp3Src); //this is returning the correct mp3 value
            return (<audio id="audio_player">
            <source id="src_mp3" type="audio/mp3" src="sounds/0010_beat_egyptian.mp3" />
            <source id="src_ogg" type="audio/ogg" src=""/>
            <object id="audio_object" type="audio/x-mpeg" width="200px" height="45px" data={mp3Src}>
                <param id="param_src" name="src" value={mp3Src} />
                <param id="param_src" name="src" value={mp3Src} />
                <param name="autoplay" value="false" />
                <param name="autostart" value="false" />
            </object>
            </audio>    
            );

    }

    export default AudioPlayer;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import './music-player.css';

var sounds = [{"title" : "Egyptian Beat", "artist" : "Sarah Monks", "length": 16, "mp3" : "sounds/0010_beat_egyptian.mp3"}, 
        {"title" : "Euphoric Beat", "artist" : "Sarah Monks", "length": 31, "mp3" : "sounds/0011_beat_euphoric.mp3"},
        {"title" : "Latin Beat", "artist" : "Sarah Monks", "length": 59, "mp3" : "sounds/0014_beat_latin.mp3"}, 
        {"title" : "Pop Beat", "artist" : "Sarah Monks", "length": 24, "mp3" : "sounds/0015_beat_pop.mp3"},
        {"title" : "Falling Cute", "artist" : "Sarah Monks", "length": 3, "mp3" : "sounds/0027_falling_cute.mp3"}, 
        {"title" : "Feather", "artist" : "Sarah Monks", "length": 6, "mp3" : "sounds/0028_feather.mp3"},
        {"title" : "Lose Cute", "artist" : "Sarah Monks", "length": 3, "mp3" : "sounds/0036_lose_cute.mp3"}, 
        {"title" : "Pium", "artist" : "Sarah Monks", "length": 3, "mp3" : "sounds/0039_pium.mp3"}];

ReactDOM.render(<App sounds={sounds} />, document.getElementById('root'));

registerServiceWorker();
like image 240
Sarah Avatar asked May 22 '17 20:05

Sarah


1 Answers

After some experimenting I discovered that the mp3 file needs to be imported (using import) in order to be able to play it within this environment.

So i've found a solution and edited my AudioPlayer component as follows (which works perfect):

import React, { Component } from 'react';
import './music-player.css';
//Now we import the mp3 file that this JavaScript file uses.
//This will ensure that when the project is built, 
//webpack will correctly move the mp3 file into the build folder, 
//and provide us with the right paths.  
//See docs: https://create-react-app.dev/docs/adding-images-fonts-and-files/
import mp3_file from './sounds/0010_beat_egyptian.mp3'; 

const AudioPlayer = function(props) {
    
        return (<audio id="audio_player">
        <source id="src_mp3" type="audio/mp3" src={mp3_file}/>
        <source id="src_ogg" type="audio/ogg" src=""/>
        <object id="audio_object" type="audio/x-mpeg" width="200px" height="45px" data={mp3_file}>
            <param id="param_src" name="src" value={mp3_file} />
            <param id="param_src" name="src" value={mp3_file} />
            <param name="autoplay" value="false" />
            <param name="autostart" value="false" />
        </object>
        </audio>    
        );
  
}
export default AudioPlayer;

Update 2022

In certain cases it is better to store your files (images, mp3 files etc) in the public folder. Such cases include if you need to load these files dynamically to your app. (see the docs https://create-react-app.dev/docs/using-the-public-folder/)

Due to the fact that (in my project) I have multiple mp3 files that I wanted to load dynamically I discovered that storing my mp3 files in the public folder was more suitable to my app.

Note: When storing your files in the public folder you don't need to "import" them but you must use the public environment variable (process.env.PUBLIC_URL) so that the correct path (to your public folder) will be referenced.

So here is my new solution:

  1. I created a folder in the public folder called sounds.
  2. I then changed my the Audio component (in the original post) to the following:

.

import React from 'react';
    const AudioPlayer = props => {
      
      let mp3_file = process.env.PUBLIC_URL + props.sounds[props.currentSoundIndex].mp3;
      return (<audio id="audio_player">
        <source id="src_mp3" type="audio/mp3" src={mp3_file} />
        <source id="src_ogg" type="audio/ogg" src={mp3_file} />
        Your browser does not support this audio player.
      </audio>  
      );
    }
    
    export default AudioPlayer;

Note: If you decide to store your files in the public folder then they won't be part of the webpack build and so therefore if a file is missing we won't get an error during compilation so we won't know it's missing. (The user will get a 404).

If you choose to store your files in the src folder then you need to use import so that webpack will know to include the files in the build. The upside to this is that you will get an error during compilation if any of the files don't exist.

like image 133
Sarah Avatar answered Oct 20 '22 16:10

Sarah