Reputation: 315
I'm using React.js and the web audio API to create an app that plays music.
Demo
Could you please tell me how to link the input type=range to the music being played?
And by moving input type=range, I want to change the current time of the music being played.
The source code is as follows.
let audioCtx, audioBuffer, source;
const audioURL = "/piano.mp3";
const App = () => {
const [load, setLoad] = useState(true);
const [playing, setPlaying] = useState(false);
const [total, setTotal] = useState(0);
const [current, setCurrent] = useState(0);
const audioLoad = async () => {
const response = await fetch(audioURL);
const arrayBuffer = await response.arrayBuffer();
if (arrayBuffer) {
audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
setTotal(audioBuffer.duration);
}
setLoad(false);
};
useEffect(() => {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
audioLoad();
return () => {
audioCtx.close();
audioCtx = null;
};
}, []);
const playAudio = () => {
if (!playing) {
source = audioCtx.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioCtx.destination);
source.start();
setPlaying(true);
return;
}
source.stop();
setCurrent(0);
setPlaying(false);
};
const changeSeek = (e) => {
setCurrent(e.target.value);
audioCtx.currentTime = current;
console.log(audioCtx.currentTime);
};
return (
<>
<p>Total time {total}</p>
<p>Current time {current}</p>
<button onClick={playAudio} disabled={load ? true : false}>
{playing ? "stop" : "play"}
</button>
<input
onChange={changeSeek}
value={current}
type="range"
max={total}
style={inputStyle}
/>
</>
);
};
The audio context has a currentTime property, and I thought I could change the current time of the music by assigning the value of input type=range to this property, but I was unable to do so.
Also, I couldn't figure out how to automatically move input type=range to match the current time of the music.
Upvotes: 1
Views: 1368
Reputation: 6048
BaseAudioContext.currentTime
is immutable. It represents the HW audio clock so you can't just arbitrarily set to to move things around in time. If you want to be able to seek through an AudioBuffer
, you'll have implement the seeking there, by creating an AudioBufferSourcNode
with the desired AudioBuffer
, and calling start(startTime, offset, duration)
appropriately (possibly leaving off the duration
parameter).
Or use a MediaElementAudioSourceNode
with the src
set up appropriately since a MediaElement
supports seeking. This won't be sample accurate, but perhaps that's ok for your use case.
Upvotes: 1