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();
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();
Share
Improve this question
asked May 22, 2017 at 20:18
SarahSarah
2,0033 gold badges26 silver badges40 bronze badges
8
|
Show 3 more comments
3 Answers
Reset to default 11After 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:
- I created a folder in the
public
folder called sounds. - 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.
Try:
import React, { Component } from 'react';
import mp3_file from './sounds/0010_beat_egyptian.mp3';
const AudioPlayer = function(props) {
return (
<audio src={mp3_file} controls autoPlay/>
);
}
export default AudioPlayer;
Incase this helps anyone else, I had the set up pretty much same as the OP and was using the autoplay attribute, but I'd put autoplay
instead of autoPlay
.
document.getElementById("audio_player").addEventListener("error", function(e){ console.error(e); });
At the very least you could then debug that to see if any errors are being generated. – TheJim01 Commented May 22, 2017 at 20:43localhost:3000/sounds/0010_beat_egyptian.mp3
, I would have expected the same as you. What kind of server are you using to hostlocalhost:3000
? If it's something native to React, then I guess it could make the decision to show the main app instead. That said, I'm glad you found a solution. Please consider adding it as an answer, and accepting it, so others can see your question was resolved. – TheJim01 Commented May 23, 2017 at 12:13