Tonejs / Tone.js

A Web Audio framework for making interactive music in the browser.
https://tonejs.github.io
MIT License
13.37k stars 976 forks source link

Tone.Player onload method does not work on iOS Safari #1132

Closed estikf closed 1 year ago

estikf commented 1 year ago

Hello,

I've been trying to build an application using React. Its deployed on Vercel and here is the link: https://loopbox.live/1

The onload method of the Tone.Player does not work on iOS Safari. I update the application state after all the assets have loaded. It works in Windows / Android / Chrome / Firefox but I couldnt figure out why it does not load the audio on iOS Safari.

I serve audios from the public folder. Here is some example code:



export const usePlayers = (id) => {
    const [loadingProgress, setLoadingProgress] = useState(0);

    const bpm = loopkits[id] ? loopkits[id].bpm : "124";
    const category = loopkits[id] ? loopkits[id].category : "";

    const players = useMemo(() => {
        return (
            loopkits[id] &&
            loopkits[id].loops.map((i) => {
                return {
                    title: i.title,
                    parent: i.parent,
                    status: i.status,
                    loopEnd: i.loopEnd,
                    startColor: i.startColor,
                    stopColor: i.stopColor,
                    loop: new Tone.Player({
                        url: process.env.PUBLIC_URL + `${i.url}`,
                        onload: () => setLoadingProgress((state) => state + 1),
                    }).toDestination(),
                };
            })
        );
    }, [id]);

    return [players, bpm, loadingProgress, category];
};

};
estikf commented 1 year ago

I have resolved the loading problem by converting .ogg files into .mp3 files. BUT now in some Apple devices (iPhone 11 for example) the audio does not start. There is no problem on Windows or Android devices. I trigger the Tone.start() by pressing a button. I dont know why is it so tricky to play some audio in iOS. I would be very happy if someone can help me.


const startContext = async () => {
        await Tone.start();
        Transport.start();
    };

const startPlayer = async (parent, title, loopEnd) => {
        if (!context.isStarted) {
            await startContext();
        }

        if (Tone.context.state !== "running") {
            Tone.context.resume();
        }
        ... play audios etc..
}
estikf commented 1 year ago

I have realized that the problem is related to iPhone's silent mode switch. It mutes the web audio as people mentioned in other issues.

I have tried unmute.js and unmute-ios-audio packages but none of them did work (probably they are outdated for recent the iOS versions). I have also tried playing a HTML

I am closing it because there are other posts related with silent mode.