How to play multiple audio sequentially with ionic Media plugin

1.5k views Asked by At

I am trying to play multiple audio files with ionic media plugin : https://ionicframework.com/docs/native/media. but I am having a hard time making it work as a playlist without using a timeout function.

Here is what I have tried out

playOne(track: AudioFile): Promise<any> {


 return new Promise(async resolve =>{

      const AudFile =  await this.media.create(this.file.externalDataDirectory+track.trackUrl);


       await resolve(AudFile.play())

   });


  }

Then to play All , I have this :

async playAll(tracks: AudioFile[]): Promise<any>{
    let player = (acc, track:AudioFile) => acc.then(() => 

        this.playOne(track)


    );

   tracks.reduce(player, Promise.resolve());
  }

This way they are all playing at the same time.

But If The PlayOne method is wrapped in a timeout function, the interval of the milli seconds set on the timeout exists among the play list, but one does not necessarily finish before the other starts and sometimes it waits for a long time before the subsequent file is plaid.

The timeout implementation looks like this :

playOne(track: AudioFile): Promise<any> {


 return new Promise(async resolve =>{
     setTimeout(async ()=>{
      const AudFile =  await this.media.create(this.file.externalDataDirectory+track.trackUrl);


       await resolve(AudFile.play())
     },3000)
   });


  }

Digging into ionic wrapper of the plugin, the create method looks like this :

/**
 * Open a media file
 * @param src {string} A URI containing the audio content.
 * @return {MediaObject}
 */
Media.prototype.create = function (src) {
    var instance;
    if (checkAvailability(Media.getPluginRef(), null, Media.getPluginName()) ===
        true) {
        // Creates a new media object
        instance = new (Media.getPlugin())(src);
    }
    return new MediaObject(instance);
};
Media.pluginName = "Media";
Media.repo = "https://github.com/apache/cordova-plugin-media";
Media.plugin = "cordova-plugin-media";
Media.pluginRef = "Media";
Media.platforms = ["Android", "Browser", "iOS", "Windows"];
Media = __decorate([
    Injectable()
], Media);
return Media;
 }(IonicNativePlugin));

Any suggestion would be appreciated

3

There are 3 answers

1
kplus On BEST ANSWER

I eventually got it to work with a recursive function. This works as expected.

PlayAllList(i,tracks: AudioFile[]){
    var self = this;

 this.Audiofile = this.media.create(this.file.externalDataDirectory+tracks[i].trackUrl);

 this.Audiofile.play()
   this.Audiofile.onSuccess.subscribe(() => {
    if ((i + 1) == tracks.length) {
      // do nothing
     } else {
       self.PlayAllList(i + 1, tracks)
     }



  })
}

Then

this.PlayAllList(0,tracks)

If there is any improvement on this, I will appreciate.

2
lsmod On

You may get it working by looping over your tracks and await playOne on each track.

async playAll(tracks: AudioFile[]): Promise<any> {
  for (const track of tracks) {
    await this.playOne(track);
  }
}

If I'm not mistaking play function doesn't block until playing the audio file is finished. It doesn't return a promise either. A work around would be to use a seTimeout for the duration of the track

playOne(track: AudioFile): Promise<any> {
  return new Promise((resolve, reject) => {
    const audFile =  await this.media.create(this.file.externalDataDirectory+track.trackUrl);
    const duration = audFile.getDuration(); // duration in seconds

    AudFile.play();
      setTimeout(() => {
        resolve();
      },
      duration * 1000 // setTimeout expect milliseconds
    );
  });
}
2
Davy On

I think you will be better of with the Web Audio API. I have used it before, and the possibilities are endless.

Apparently it can be used in Ionic without issues: https://www.airpair.com/ionic-framework/posts/using-web-audio-api-for-precision-audio-in-ionic

I have used it on http://chordoracle.com to play multiple audio samples at the same time (up to 6 simultaneous samples for each string of the guitar). In this case i also alter their pitch to get different notes.

In order to play multiple samples, you just need to create multiple bufferSources: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createBufferSource

Some links to get you started: