A guide to playing a series of audio files in succession using the Ionic Media plugin

I have been attempting to create a playlist of multiple audio files using the Ionic media plugin from here. However, I am struggling to achieve this without resorting to using a timeout function.

Here is my current approach:

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());
   });
}

To play all tracks in the playlist, I have implemented the following method:

async playAll(tracks: AudioFile[]): Promise<any>{
    let player = (acc, track:AudioFile) => acc.then(() => 
        this.playOne(track)
    );
   tracks.reduce(player, Promise.resolve());
}

Unfortunately, with this setup, all tracks are playing simultaneously. So, I tried wrapping the playOne method in a timeout function to introduce a delay between tracks. This resulted in some tracks waiting an excessively long time before being played:

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);
   });
}

Upon further investigation into the Ionic wrapper for the plugin, I found that the create method is structured as follows:

/**
 * 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));

If anyone has suggestions on how to improve this playlist functionality, I would greatly appreciate it.

Answer №1

To achieve the desired functionality, you can iterate through your tracks and use the playOne method on each track while awaiting its completion.

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

It's important to note that the play function does not block execution until the audio file finishes playing and it also does not return a promise. One possible workaround is to utilize a setTimeout based on the duration of the track.

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

    audioFile.play();
    
    setTimeout(() => {
      resolve();
    }, 
    duration * 1000 // setTimeout expects milliseconds
    );
  });
}

Answer №2

After much trial and error, I was able to make it function using a recursive approach. The results were just as I had anticipated.

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)
     }



  })
}

Subsequently,

this.PlayAllList(0,tracks)

If there are any suggestions for improvement, please feel free to share. Thank you.

Answer №3

Exploring the vast possibilities of the Web Audio API can greatly enhance your projects. The flexibility it offers is truly endless.

It's interesting to note that the Web Audio API can seamlessly integrate with Ionic, as highlighted in this informative article:

An example of its practical application can be seen on , where I utilized it to simultaneously play multiple audio samples (up to 6 for each guitar string) while manipulating their pitch to achieve distinct notes.

To enable the playback of multiple samples, simply create multiple bufferSources: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createBufferSource

If you're interested in delving into using the Web Audio API, here are some useful resources:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating dynamic dropdown menus using JSON files in jQuery mobile is a useful technique for enhancing user experience on

I am working with a massive table (8 MBytes) that I need to filter using a small JavaScript application. The process works as follows: Countries Regions Skills I want the user to select one country, one region, and multiple skills as filters. Based on ...

Incorporate JQuery into your NodeJS project by leveraging the existing minified file

Can we integrate JQuery into Node.js and make JQuery AJAX calls without altering the syntax by using a pre-downloaded minimized JQuery file? To clarify, I have the minified file and wish to incorporate it into Node.js in this manner: var jquery = require( ...

Guide on how to verify if a component with a specific name is registered within the Composition API of Vue 3

My current situation involves a template that loads dynamic components based on their names: <template> <div> <div> <div> <component :is="getFormRenderer" &g ...

Combining Mocha, BlanketJS, and RequireJS has resulted in the error message "No method 'reporter'."

While using Mocha with RequireJS, my tests are running smoothly. However, I encountered an issue when trying to incorporate blanket code coverage. The error Uncaught TypeError: Object #<HTMLDivElement> has no method 'reporter' keeps popping ...

Refreshing a <div> element in Django, yet there is no visible update

As I utilize a barcode scanner to add objects to my array list, the data is populated after each scan depending on the scanning speed of the user. To exhibit this data, I have designed a dedicated page. My intention is to avoid refreshing the entire page b ...

Why aren't the validations being set when creating Angular forms using formControl.values?

I had to structure the form in a specific way in my app.ts file -> courseNameControl = new FormControl("", [Validators.required,Validators.minLength(2)]); contentControl = new FormControl("", Validators.required); form = { cours ...

What is the best way to dynamically swap out an image within an element?

Is there a way to dynamically replace this image without deleting the HTML SVG element and re-rendering it? xlink:href="http://missosology.info/forum/download/file.php?avatar=11666_1307312313.jpg" CODE: https://jsfiddle.net/bfv17f0e/ <svg class="clip ...

Exploring the Concept of Angular4 Component Nesting and Input Issues

I've taken on the challenge of completing an exercise from the book "Angular From Theory To Practice - Asim Hussain". The exercise involves refactoring an app using Angular CLI instead of having all components in the same file. You can find a sample f ...

Is there a way to keep the text animation going even when I'm not hovering over it with the cursor?

Is there a way to make text continue animating on the page even when the cursor is not placed on it? I understand the hover function, but how can I ensure the text keeps animating without interruption? $(document).ready(function () { $("#start&q ...

Discovering the absent number within a cyclical array

Looking to find the missing number between two arrays in a cyclical manner using either Javascript or jQuery. It's easy to find all missing numbers, but I specifically need to identify the single missing number within the range of the second array whi ...

Condition-based React state counter starts updating

In my current project, I have developed the following React component: import React from "react"; import ReactDOM from "react-dom"; import { WidthProvider, Responsive } from "react-grid-layout"; import _ from "lodash"; const ResponsiveReactGridLayout = Wi ...

Unable to execute JS script to navigate back to prior page with webdriver

Here is my code snippet: JavascriptExecutor jse = (JavascriptExecutor)driver; jse.executeScript("window.history.go(-1);"); The code above isn't working. I've tried casting the webdriver instance but it doesn't work every time. I prefer not ...

Turn off the ability to drag on an HTML page

Need help with creating an HTML etch-a-sketch! I have a div container with multiple div elements inside it, all set up with CSS grid display. HTML structure: <div id="canvas"></div> To populate the canvas with div elements, I'v ...

Removing redundant names from an array using Typescript

My task involves retrieving a list of names from an API, but there are many duplicates that need to be filtered out. However, when I attempt to execute the removeDuplicateNames function, it simply returns an empty array. const axios = require('axios&a ...

Choosing Drop Down Options Dynamically with Jquery

I have a total of 4 Drop Downs on my page. https://i.stack.imgur.com/6tHj5.png Each drop-down initially displays a "--select--" option by default. Additionally, each drop-down has a unique ID assigned to it. The second drop-down is disabled when the abov ...

Error injecting Angular components

Here is the structure of my HTML file: <html> <head> <title>PLD Interaction pattern</title> <link href="css/bootstrap.min.css" rel="stylesheet" type="text/css"/> </head> <body ng-app="myT ...

Ensure that all MongoDB write operations have been completed before proceeding with a find operation

I am in need of a store js object that can manage a mongodb collection in a specific way: store.insert(thing); // triggered from a pubsub system without waiting for the insert to complete store.get(); // should return a promise that resolves to the items ...

Unresponsive Radio Buttons in HTML

Have you ever encountered the issue where you can't seem to select radio buttons despite them having a confirmed name attribute? Here is an example of the HTML code: <div id="surveys-list" class="inline col-xs-12"><div> <div class="i ...

Populate the content within a div element with specified height and width by utilizing JavaScript and jQuery

I need help with filling a fixed height div with long text retrieved via ajax in json format. For example, if I have a div with a height of 500px and width of 300px, with a font size of 16px. Is there a javascript recursive method that can fill the data ...

Unable to substitute a value using the useState hook in React

Whenever I click a key, I attempt to update the value of a variable but it appears not to be working as intended. ↓ The current implementation is not effective and needs improvement import React, { useState, useEffect } from 'react'; const Li ...