Reputation: 992
I want to play a single audio file (mp3) and my only problem is media length.
It works just fine on Android 5.0.1, but on 4.4.2/4.4.4 it doesn't work!
With native implementation I get a value but it's incorrect and if I use the Media plugin API (from Phonegap) the media.duration
is undefined and media.getDuration()
returns -1.
I'm trying to get duration only after loadedmetadata
event is fired, so this could not be the problem.
The native implementation is done through js with new Audio()
, no DOM element involved.
The file is stored on sdcard, and src looks like file:///storage/sdcard/audio.mp3
. Everything else regarding html5 audio api works, but duration.
Are there any solutions to fix this?
Upvotes: 1
Views: 938
Reputation: 456
For the sake of reference:
audio.addEventListener('durationchange', function(e) {
console.log(e.target.duration); //FIRST 0, THEN REAL DURATION
});
worked for me.
Credit: this stackowerflow question
Upvotes: 0
Reputation: 992
Thanks to @tawpie's answer I figured out a workaround for this issue I'm having.
That setInterval
made me thing about my custom seekbar been updated (correctly) while the audio is playing and in calculating the width of it I was using audio duration value and from that results that the duration is working after media file play method is fired.
The problem is that loadedmetadata
event doesn't return the correct duration value (in some browsers like android webView), but after audio played for at least 1s the duration is updated and you can use it.
So you can forget about loadedmetadata
event and jump straight to canplay
event and from there you can make something like this:
var myAudio = new Audio();
myAudio.src = 'file://mnt/sdcard/audio.mp3';
myAudio.load();
myAudio.correctDuration = null;
myAudio.addEventListener('canplay', function(){
myAudio.play();
myAudio.muted = true;
setTimeout(function(){
myAudio.pause();
myAudio.currentTime = 0;
myAudio.muted = false;
myAudio.correctDuration = myAudio.duration;
},1000);
});
...of course, you can use volume = 0.0/1.0
instead of mute.
Another method would be to create a helper function (in my case - a AngularJS service) which takes your src
value and uses the code above and returns the correctDuration. This one is preferred if you have listeners to audio timeUpdate
which changes the DOM.
The Media plugin works exactly the same way - if the audio haven't played for at least 1s you cannot use getDuration()
method or duration
property inside a interval/timeout wrapper to get the correct duration.
I think the video element behaves similarly. I'll test it these days.
Hope this workaround helps!
Upvotes: 2
Reputation: 271
Try Media.node.duration. That works on windows... For what it's worth, as long as getDuration is called in an interval, I don't have any problems on Android 4.4. But I'm using just the media plugin new Media(src, onSuccess, onError, playbackStatus)
and not the HTML5 player.
Upvotes: 1
Reputation: 9471
Hardcoded values. It's a pain, but you can do this if the files are local.
I ran into an issue where chrome was reporting different duration values than other browsers, and this is where we landed. I know it's not really a solution, but it works.
OR... you can use some external process to generate a json of duration times, and reference those values at runtime.
Upvotes: 0