38

I am using Chrome. In my dev tools console, I tried the following:

enter image description here

Everything works as expected except last line. Why can't I set currentTime on it?

Also in general, I am finding this whole HTML5 Audio thing to not be very reliable. Is there a robust javascript wrapper that fallsback to flash ?

Karlo
  • 1,630
  • 4
  • 33
  • 57
Rajat
  • 32,970
  • 17
  • 67
  • 87
  • 1
    Audio has a 'loadedmetadata' event that fires when the src has been loaded – echopeak May 05 '16 at 06:51
  • @echopeak is there a working example I can look at? I am more interested in the `seek` event as I want to play the audio from a different start point. – Rajat May 10 '16 at 02:58
  • can you provide a link to download the audio? – Chicodelarose May 11 '16 at 15:47
  • 1
    @Rajat _"Why cant I set `currentTime` on it?"_ Cannot reproduce – guest271314 May 16 '16 at 08:04
  • 1
    I am facing the same issue. It's working on a piece of code, but when i integrate it in a Django application, it fails. It works on Firefox but not on Google Chrome. Video / Audio file doesn't matter, it happens with any file i try on the code. The time i am trying to seek to is less than the duration of the video. – atb00ker Jun 06 '18 at 12:02
  • @atb00ker any answer on why this happens when starting a django server? I am experiencing the same, also only when accessing the same files via a django server. – AdagioMolto Jun 28 '19 at 00:48
  • @AdagioMolto The answer here helped me find the issue: https://stackoverflow.com/a/42977670/6410464 – atb00ker Jun 30 '19 at 17:40

10 Answers10

14

You need to do something like this (if you use jQuery)

$('#elem_audio').bind('canplay', function() {
  this.currentTime = 10;
});

or in Javascript

var aud = document.getElementById("elem_audio");
aud.oncanplay = function() {
    aud.currentTime = 10;
};

The reason behind for this setup is you need to make sure the audio is ready to play.

Netorica
  • 18,523
  • 17
  • 73
  • 108
  • Also you can use `seeked` event. [Here is example](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events) in the end of page. – Bob Sponge May 05 '16 at 06:50
  • 2
    So i tried adding `x.addEventListener('seeked', function () { x.play() })` right before updating the `currentTime` to `10` and the result is the same. When the audio plays, it starts from 0. – Rajat May 05 '16 at 07:14
  • @Rajat I don't know if this will work for you but you tried also the event `canplaythrough`? – Netorica May 17 '16 at 02:46
  • 1
    @OlgaReal Actually `canplay` works. I was doing `.bind('canplay', function() { this.currentTime = 10; this.play() });` and that doesn't work. `play()` needs to be outside the handler. – Rajat May 17 '16 at 06:11
14

Check your HTTP server configuration, in my testing environment ( Chrome 69 on Mac OS) setting currentTime property of audio element works only when the audio source is served by a HTTP server support persistent connection.

If the HTTP server you used support persistent connection, you will found (in Chrome DevTool) the Connection field of response headers of your audio source be keep-alive. By contrast if the audio source is served by a persistent connection incompatible server, there will be no Connection field in response headers.

The status code of your audio source HTTP request will be a reference too, 206 Partial Content for persistent connection supported server, 200 OK for an inferior one.

Bono Lv
  • 577
  • 5
  • 7
  • 1
    I can confirm the Webserver can be the reason for this issue. But in my test environment, both my local DEV server and my live server have a `Connection: keep-alive` in the _Response Headers_. I see the difference in the `Status Code: 200` vs `Status Code: 206`. Additional I see in the working live server a `Accept-Ranges: bytes`, which I am missing in my DEV server. – Tsunamis Dec 11 '18 at 08:55
  • 6
    I had to make sure `Accept-Ranges: bytes` was present in the response headers - that did the trick! – brianarpie Apr 10 '19 at 21:06
  • This happened to me while serving a small mp3 file from Spring Boot 2. Thanks for avoiding me headaches!! – FonzTech Feb 07 '20 at 14:06
  • 1
    thanks @brianarpie, I had to change my context.Response.Headers.Add("Accept-Ranges", "0-" + size); to context.Response.Headers.Add("Accept-Ranges", "bytes 0-" + size); So yeah, I did append the bytes infront of the range string, and that did the trick! One thing i need to point out is that, i didn't have an issue when i used the prior code block for video streaming. It is weird that for audio streaming, i need to add "bytes" infront of the range string. – Ji_in_coding Jun 04 '20 at 14:31
  • this worked... can someone explain why??? @brianarpie – Truman Purnell Jan 23 '21 at 07:47
  • @Ji_in_coding Thanks a lot! Your code snippet saved me lots of neurons, from the few I still have left. :-D – Unknown Coder Feb 10 '23 at 22:44
7

I had the same problem, and the reason was missing headers on the mp3 file, like:

Content-Length, Content-Range, Content-Type

Koby Douek
  • 16,156
  • 19
  • 74
  • 103
Nexx
  • 327
  • 4
  • 4
6

Why cant I set currentTime on it?

Could not reproduce currentTime being set to 0 after setting to 10. Is 18.mp3 duration less than 10?

var request = new XMLHttpRequest();
request.open("GET", "/assets/audio/18.mp3", true);
request.responseType = "blob";    
request.onload = function() {
  if (this.status == 200) {
    var audio = new Audio(URL.createObjectURL(this.response));
    audio.load();
    audio.currentTime = 10;
    audio.play();
  }
}
request.send();

jsfiddle http://jsfiddle.net/Lg5L4qso/3/

guest271314
  • 1
  • 15
  • 104
  • 177
1

I ran into this problem after I'd started to use the PHP Server extension to VS Code to serve my HTML/PHP local testing. The problem was resolved for me by going back to my old Abysswebserver setup.

So, it's not simply that "you can't manipulate .currentTime on locally served files" but rather that "you need to pick a server that gives you the right headers". The Status entry for my file from AbyssWebserver, for example, read "Status Code: 206 Partial Content" while the one from PHP Server read "Status Code: 200 OK".

There are other differences though so there may be more to this than just the Status entry. See https://github.com/brapifra/vscode-phpserver/issues/85, for a full header comparison.

MartinJ
  • 333
  • 2
  • 13
1

If you want to return to the beginning of the audio after it has been played, use load().

// x.currentTime = 0;
x.load();

( https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/load )

drytt
  • 51
  • 1
  • 8
  • 1
    Sorry but your first affirmation is incorrect and you are misinterpreting the quote from the documentation. – Ben Souchet Dec 30 '21 at 22:15
  • @BenSouchet Thank you for your comment. Could you tell me why you think the way you do? – drytt Jan 02 '22 at 12:49
  • you can use `currentTime` to retrieve the value for example when the audio is on pause, so it's no only "used when the media **has not yet been played**". The quote from the documentation only state that **IF** the media isn't playing, the `currentTime` indicate the current/start position for the media. The next line form the docs is "Setting `currentTime` to a new value seeks the media to the given time, if the media is available." so you can change/update the currentTime. So you can `play()`, then `pause()` then edit `currentTime`, then `play()` – Ben Souchet Jan 02 '22 at 13:01
  • Thank you for your reply. I saw your comment and understood the content. Therefore, I removed the first half of the description. Thank you very much for your suggestion. – drytt Jan 06 '22 at 14:27
  • I updated my vote accordingly :) – Ben Souchet Jan 06 '22 at 16:19
1

this worked for me:

var callaudio = audio; // the audio variable
     function fetchAudioFile() {
         var requestObj = new Request(callaudio.src, {
             method: 'GET',
             headers: {
                 'Accept-Ranges': '1000000000'
             },
             referrerPolicy: 'no-referrer'
         });

         fetch(requestObj).then(function (response) {
             returnresponse;
         }).then(async function (outcome) {
             const blob = await outcome.blob();
             const url = window.URL.createObjectURL(blob);
             callaudio.src = url;
         });
     };
     fetchAudioFile();
Sebastiano Schwarz
  • 1,060
  • 2
  • 13
  • 32
0

My guess is that '10' is longer that you mp3's length.

But that logs the length of mp3 instead of '0'.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Arjenloeb
  • 104
  • 8
0

The only solution for setting currentTime I got to work reliably was using the onprogress event.

audio.onprogress = function() {
  if (audio.currentTime == 0) {
    audio.currentTime = 10;
  }
}
ultra
  • 1
  • 1
  • This creates an infinite loop because when `audio.currentTime = xxx` it is immediately set to `0`, causing the `audio.onprogress` to be called again, where the `audio.currentTime` is equal to `0` again. Then, everything repeats again forever. – Evandro Coan Apr 09 '20 at 18:12
0

The solution which worked for me was not setting "src" on directly, but use with type attribute, maybe type attribute is helping browser some way.

user2541867
  • 344
  • 4
  • 12