GithubHelp home page GithubHelp logo

rnplaysound's Introduction

React native sound

Table of content

Demo

Link youtube: https://www.youtube.com/watch?v=OfUqaofrcMw

Library and installation

npm install react-native-sound --save
react-native link react-native-sound
npm install @react-native-community/slider --save
npm install --save react-native-vector-icons
react-native link react-native-vector-icons

Usage

Load sound from the app bundle

  • Copy your audio files into folder /android/app/src/main/res/raw (if not exists, create it)
  • Notice that your audio's name in folder raw should be like this: File-based resource names must contain only lowercase a-z, 0-9, or underscore or you will face this error when run app

Load sound from the network

  • Same as Load sound from the app bundle

Load sound from other directories

  • Instead of use path like previous 2 types before, we use like this:
path: require('./sounds/Play-Doh-meets-Dora_Carmen-Maria-and-Edu-Espinal.mp3')
  • And when we create new sound, the second parameter is the callback, not the basePath
if (currentAudio.isRequired === true) {
    const newPlayer = new SoundPlayer(require('./sounds/Play-Doh-meets-Dora_Carmen-Maria-and-Edu-Espinal.mp3'), (error) => callback(error, newPlayer));
    ...
}
...
  • Notice that your audio's name in this case should be like this: File-based resource names must not contain space character or any special characters or you will face this error when run app

Steps

Step 1: Install all necessary libraries

Step 2: Create audio-helper

Step 2.1: Create interfaces and types

  • Create type SoundFileType: used for create a list of sounds we will play
type SoundFileType = {
    type: 'app-bundle';
    name: string;
    path: string;
    basePath: string;
} | {
    type: 'network';
    name: string;
    path: string;
} | {
    type: 'directory';
    name: string;
    path: NodeRequire;
};
  • Create type AudioStatusType: when we play sound, there are many states such as: loading, error, play, pause, next, previous,...
type AudioStatusType = 'loading' | 'success' | 'error' | 'play' | 'pause' | 'next' | 'previous' | 'stop';
  • Create interface IUseAudioHelper for next step: parameter of hook useAudioHelper
interface IUseAudioHelper {
    listSounds: ISoundFile[];
    timeRate?: number;
}

Step 2.2: Create hook useAudioHelper

Hook useAudioHelper has all methods, values we need like: play, pause, currentTime,...

Create state variables:

const [listSounds, setListSounds] = React.useState(request.listSounds);
const [timeRate, setTimeRate] = React.useState(request.timeRate || 15);
const [status, setStatus] = React.useState<AudioStatusType>('loading');

Initialize sound player:

const [duration, setDuration] = React.useState(0);
const [player, setPlayer] = React.useState<SoundPlayer>(null);
function playWithPlayer(player: SoundPlayer) {
    if (player) {
        player.play(playComplete);
        setStatus('play');
    }
}

function initialize() {
    setStatus('loading');
    if (listSounds.length > 0) {
        if (player) {
            player.release();
        }

        const callback = (error, player: SoundPlayer) => {
            if (error) {
                setStatus('error');
                setErrorMessage(error.message);
            } else {
                setStatus('success');
                setErrorMessage('');
            }
            player.setSpeed(speed);
            setDuration(player.getDuration());
            play(player);
        }

        const currentAudio = listSounds[index];
        // If the audio is a 'require' then the second parameter must be the callback.
        let newPlayer: SoundPlayer = null;
        switch(currentAudio.type) {
            default: break;
            case 'app-bundle':
                newPlayer = new SoundPlayer(currentAudio.path, currentAudio.basePath, (error) => callback(error, newPlayer));
                break;
            case 'network':
                newPlayer = new SoundPlayer(currentAudio.path, null, (error) => callback(error, newPlayer));
                break;
            case 'directory':
                newPlayer = new SoundPlayer(currentAudio.path, (error) => callback(error, newPlayer));
                break;
        }
        if (newPlayer) {
            setPlayer(newPlayer);
        }
    }
}

Current time:

const [currentTime, setCurrentTime] = React.useState(0);
React.useEffect(() => {
    const interval = setInterval(() => {
        if (player && status === 'play') {
            player.getCurrentTime((seconds: number) => {
                setCurrentTime(seconds);
            })
        }
    }, 100);

    return () => clearInterval(interval);
});

Speed

const [speed, setSpeed] = React.useState(1);
    React.useEffect(() => {
        if (player) {
            player.setSpeed(speed);
        }
    }, [speed]);

Initialize sound player every time we play new sound:

const [index, setIndex] = React.useState(0);
React.useEffect(() => {
    initialize();
}, [index]);

Play sound

function playComplete(isEnd: boolean) {
    if (isEnd === true) {
        next();
    }
}

function play() {
    if (player) {
        player.play(playComplete);
        setStatus('play');
    }
}

Pause sound

function pause() {
    if (player) {
        player.pause();
        setStatus('pause');
    }
}

Stop sound

function stop() {
    if (player) {
        player.stop();
        setStatus('stop');
    }
}

Next sound

function next() {
    if (player && index < listSounds.length - 1) {
        player.release();
        setCurrentTime(0);
        setStatus('next');
        setIndex(index + 1);
    }
}

Previous sound

function previous() {
    if (player && index > 0) {
        player.release();
        setCurrentTime(0);
        setStatus('previous');
        setIndex(index - 1);
    }
}

Seek to time

function seekToTime(seconds: number) {
    if (player) {
        player.setCurrentTime(seconds);
        setCurrentTime(seconds);
    }
}

Increase time

function increaseTime() {
    if (player) {
        player.getCurrentTime((seconds) => {
            if (seconds + timeRate < duration) {
                seekToTime(seconds + timeRate)
            } else {
                seekToTime(duration);
            }
        });
    }
}

Decrease time

function decreaseTime() {
    if (player) {
        player.getCurrentTime((seconds) => {
            if (seconds - timeRate > 0) {
                seekToTime(seconds - timeRate);
            } else {
                seekToTime(0);
            }
        });
    }
}

Other functions:

function formatTimeString(value: number) {
    return new Date(value * 1000).toISOString().substr(11, 8)
}

function getDurationString() {
    return formatTimeString(duration);
}

function getCurrentTimeString() {
    return formatTimeString(currentTime);
}

function getCurrentAudioName() {
    return listSounds[index].name;
}

function isDisabledButtonPlay() {
    return status === 'loading' || status === 'play';
}

function isDisabledButtonPause() {
    return status === 'loading' || status === 'pause' || status === 'stop';
}

function isDisabledButtonStop() {
    return status === 'loading' || status === 'stop';
}

function isDisabledButtonNext() {
    return status === 'loading' || index === listSounds.length - 1;
}

function isDisabledButtonPrevious() {
    return status === 'loading' || index === 0;
}

Return necessary functions, variables

return {
    status,
    duration,
    currentTime,
    play,
    pause,
    stop,
    next,
    previous,
    increaseTime,
    decreaseTime,
    durationString: getDurationString(),
    currentTimeString: getCurrentTimeString(),
    currentAudioName: getCurrentAudioName(),
    isDisabledButtonPlay: isDisabledButtonPlay(),
    isDisabledButtonPause: isDisabledButtonPause(),
    isDisabledButtonStop: isDisabledButtonStop(),
    isDisabledButtonNext: isDisabledButtonNext(),
    isDisabledButtonPrevious: isDisabledButtonPrevious(),
    seekToTime,
    timeRate,
    speed,
    setSpeed,
}

Step 3: Apply hook useAudioHelper

const player = useAudioHelper({
    listSounds: [
        { type: 'app-bundle', path: 'blue_dream_cheel.mp3', name: 'Blue Dream - Cheel', basePath: SoundPlayer.MAIN_BUNDLE },
        { type: 'app-bundle', path: 'know_myself_patrick_patrikios.mp3', name: 'Know Myself - Patrick Patrikios', basePath: SoundPlayer.MAIN_BUNDLE },
        { type: 'directory', path: require('./sounds/Play-Doh-meets-Dora_Carmen-Maria-and-Edu-Espinal.mp3'), name: 'Play Doh meets Dora - Carmen Maria and Edu Espinal', },
        { type: 'network', path: 'https://raw.githubusercontent.com/uit2712/RNPlaySound/develop/sounds/Tropic%20-%20Anno%20Domini%20Beats.mp3', name: 'Tropic - Anno Domini Beats', },
    ],
    timeRate: 15,
    isLogStatus: true,
});

References

React native sound

Link: https://www.npmjs.com/package/react-native-sound

React native sound demo

Link: https://github.com/zmxv/react-native-sound-demo

React native sound player preview

Link: https://github.com/benevbright/react-native-sound-playerview

rnplaysound's People

Contributors

uit2712 avatar

Stargazers

Bogdan Georgian Alexa avatar Sayyid Shalahuddin avatar Reinhart Andreas avatar  avatar Eduardo Marques Nepomuceno avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.