Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MediaManager isn't getting the correct duration #42

Closed
kylesziv opened this issue Mar 10, 2016 · 8 comments
Closed

MediaManager isn't getting the correct duration #42

kylesziv opened this issue Mar 10, 2016 · 8 comments

Comments

@kylesziv
Copy link

We are pulling audio from AWS and it appears that it always has the incorrect duration. The current position will go above the total duration. Any ideas what is going on?

@arielfaur
Copy link
Owner

Is your audio in MP3 format? I am also pulling audio from AWS and works fine on my end.

@kylesziv
Copy link
Author

This is my enviroment:

Cordova CLI: 6.0.0
Gulp version: CLI version 3.9.0
Gulp local: Local version 3.9.1
Ionic Version: 1.2.4-nightly-1917
Ionic CLI Version: 1.7.14
Ionic App Lib Version: 0.7.0
ios-deploy version: Not installed
ios-sim version: 4.1.1
OS: Mac OS X El Capitan
Node Version: v0.10.32
Xcode version: Xcode 7.2 Build version 7C68

And my plugins:

com.phonegap.plugins.facebookconnect 1.0.1.1 "Facebook"
com.pushwoosh.plugins.pushwoosh 4.2.0 "Pushwoosh"
cordova-plugin-audio-recorder-api 0.0.1 "AudioRecorderAPI"
cordova-plugin-console 1.0.2 "Console"
cordova-plugin-device 1.1.1 "Device"
cordova-plugin-dialogs 1.2.0 "Notification"
cordova-plugin-file 4.1.1 "File"
cordova-plugin-insomnia 4.2.0 "Insomnia (prevent screen sleep)"
cordova-plugin-media 2.0.0 "Media"
cordova-plugin-network-information 1.2.0 "Network Information"
cordova-plugin-nowplaying 1.0.0 "NowPlaying"
cordova-plugin-remotecommand 1.0.0 "RemoteCommand"
cordova-plugin-splashscreen 3.1.0 "Splashscreen"
cordova-plugin-statusbar 2.1.1 "StatusBar"
cordova-plugin-transport-security 0.1.1 "App Transport Security"
cordova-plugin-whitelist 1.2.1 "Whitelist"
cordova-plugin-x-socialsharing 5.0.10 "SocialSharing"
cordova-sqlite-storage 0.8.4-dev "Cordova sqlite storage plugin (core version)"
ionic-plugin-keyboard 1.0.8 "Keyboard"

What is your version of Media and Angular? Maybe there is a problem with my environment?

@arielfaur
Copy link
Owner

I am using cordova-plugin-media 2.2.0 with ionic 1.2.4. But I am on Android so I am not sure about iOS, i know it works for other users but there may be some issues depending on your plugin versions.

@kylesziv
Copy link
Author

I updated and still no luck. It looks like this is actually an issue with the media plugin because that is where the duration comes from.

@arielfaur
Copy link
Owner

Can you try this?

cordova plugin rm cordova-plugin-media

cordova plugin add cordova-plugin-media@1.0.1

@kylesziv
Copy link
Author

No dice.

So the application that we've built records audio and then pushes it to a server. The server converts it to mp3 and then through the app they have the ability to listen to it. We also have a webapp that does the same thing. All data is accessible on web or mobile. The files created by the web do not have this issue (they are originally mp3 files). The files generated by the app is m4v. I'm wondering if there is something going on with the conversion process. I'm not sure how cordova-plugin-media figures out the duration. Any ideas?

@arielfaur
Copy link
Owner

The cordova-plugin-media sucks at that, it has many issues with audio position and duration. The audio duration is not reported immediately as the audio starts playing but it needs a few cycles until the plugin can read the duration -if it can at all, it seems to fail for some audio formats. So you are dealing with m4v files, I have no experience with that format so I cannot tell.

The latest plugin version claims to have solved these issues but I am not so sure. I am working on the next version of ionic-audio which will support the new Web Audio API in addition to the media plugin.

@lxieyang
Copy link

lxieyang commented Jul 24, 2017

I've been looking into this issue for a while, and I agree with @arielfaur. It appears that it takes a short while for the plugin to be able to read the duration of the audio file, after the file starts playing. So, to come up with a work around, you need to:

  1. play the file
  2. set the volume to 0
  3. constantly check for duration until you get it.

Below is a sample sample function I just created to tackle the issue:

getDurationAndSetToPlay() {
    this.curr_playing_file = this.media.create(this.file.externalDataDirectory + "hotel_california.mp3");
    this.curr_playing_file.play();
    this.curr_playing_file.setVolume(0.0);  // you don't want users to notice that you are playing the file
    let self = this;
    this.interval = setInterval(function() {
      if(self.duration == -1) {
        self.duration = self.curr_playing_file.getDuration();
      } else {
        self.curr_playing_file.stop();
        self.curr_playing_file.release();
        self.setRecordingToPlay();
        clearInterval(self.interval);
      }
   }, 100);
}

The complete .html and .ts are shown below:

home.html:

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      <ion-icon name="musical-note"></ion-icon>&nbsp;&nbsp;
      {{ filename }}
    </ion-title>
  </ion-navbar>
</ion-header>


<ion-content padding>
  <!-- Playback section -->
  <ion-card padding text-center>
    <h1>Playback</h1>
    <ion-card-content>
      <ion-grid>
        <ion-row>
          <ion-col>
            <button ion-button color="primary" [disabled]="!is_ready">
                    &nbsp;&nbsp;<ion-icon name="skip-backward"></ion-icon>&nbsp;&nbsp;
            </button>
          </ion-col>
          <ion-col>
            <button ion-button (click)="playRecording()" color="primary" *ngIf="!is_playing" [disabled]="!is_ready">
                    &nbsp;&nbsp;<ion-icon name="play"></ion-icon>&nbsp;&nbsp;
            </button>

            <button ion-button (click)="pausePlayRecording()" color="secondary" *ngIf="is_playing" [disabled]="!is_ready">
              &nbsp;&nbsp;<ion-icon name="pause"></ion-icon>&nbsp;&nbsp;
            </button>
          </ion-col>
          <ion-col>
            <button ion-button color="primary" [disabled]="!is_ready">
                    &nbsp;&nbsp;<ion-icon name="skip-forward"></ion-icon>&nbsp;&nbsp;
            </button>
          </ion-col>
        </ion-row>
      </ion-grid>

      
      
      <!-- <button ion-button (click)="stopPlayRecording()" color="danger">
        &nbsp;&nbsp;<ion-icon name="square"></ion-icon>&nbsp;&nbsp;
      </button> -->
    </ion-card-content>
  </ion-card>

  <p>Duration: {{ duration }}</p>

  {{ message }}

</ion-content>

home.ts:

import { Component } from '@angular/core';
import { Platform, NavController, NavParams } from 'ionic-angular';

import { Media, MediaObject } from '@ionic-native/media';
import { File } from '@ionic-native/file';
import { FileTransfer, FileUploadOptions, FileTransferObject } from '@ionic-native/file-transfer';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class AudioDetail {

  filename: any;
  curr_playing_file: MediaObject;

  is_playing: boolean = false;
  is_ready: boolean = false;

  message: any;

  duration: any = -1;
  position: any;

  interval: any;

  constructor(
    public platform: Platform,
    public navCtrl: NavController,
    public navParams: NavParams,
    private file: File,
    private transfer: FileTransfer,
    private media: Media) {
      // this.item = navParams.get('file');
      this.filename = "Hotel California";
      let url = "http://fabienne.sigonney.free.fr/tranquilit%E9/Eagles%20-%20Hotel%20California%20(Acoustic).mp3";

      this.platform.ready().then(() => {
        this.file.resolveDirectoryUrl(this.file.externalDataDirectory).then((resolvedDirectory) => {
          // inspired by: https://github.com/ionic-team/ionic-native/issues/1711
          console.log("resolved  directory: " + resolvedDirectory.nativeURL);
          this.file.checkFile(resolvedDirectory.nativeURL, "hotel_california.mp3").then((data) => {
            if(data == true) {  // exist
              this.getDurationAndSetToPlay();
            } else {  // not sure if File plugin will return false. go to download
              console.log("not found!");
              throw {code: 1, message: "NOT_FOUND_ERR"};
            }
          }).catch(err => {
            console.log("Error occurred while checking local files:");
            console.log(err);
            if(err.code == 1) {
              // not found! download!
              console.log("not found! download!");
              const fileTransfer: FileTransferObject = this.transfer.create();
              fileTransfer.download(url, this.file.externalDataDirectory + "hotel_california.mp3").then((entry) => {
                console.log('download complete' + entry.toURL());
                this.getDurationAndSetToPlay();
              }).catch(err_2 => {
                console.log("Download error!");
                console.log(err_2);
              });
            }
          });
        });
      });
  }

  getDurationAndSetToPlay() {
    this.curr_playing_file = this.media.create(this.file.externalDataDirectory + "hotel_california.mp3");
    this.curr_playing_file.play();
    this.curr_playing_file.setVolume(0.0);  // you don't want users to hear that you are playing the file
    let self = this;
    this.interval = setInterval(function() {
      if(self.duration == -1) {
        self.duration = self.curr_playing_file.getDuration();
      } else {
        self.curr_playing_file.stop();
        self.curr_playing_file.release();
        self.setRecordingToPlay();
        clearInterval(self.interval);
      }
    }, 100);
  }

  setRecordingToPlay() {
    this.curr_playing_file = this.media.create(this.file.externalDataDirectory + "hotel_california.mp3");
    console.log("audio file set");
    this.message = "audio file set";
    this.is_ready = true;
  }

  playRecording() {
    this.curr_playing_file.play();
    this.is_playing = true;
  }

  pausePlayRecording() {
    this.is_playing = false;
    this.curr_playing_file.pause();
  }

  stopPlayRecording() {
    this.is_playing = false;
    this.curr_playing_file.stop();
    this.curr_playing_file.release();
  }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants