How to play audio using JS efficiently and without delay - javascript

I am building a very simple JS code where I can play "organ" (like a piano) clicking on buttons just like if I were playing a piano, tapping in the keys. I recorded 10 samples of 10 notes of my organ and saved each separetly file as mp3.
Then I created 10 buttons, when I click each button the sampled sound of that note is played. The problem that I am facing, is that there is always a small delay (like 200 to 300 ms) between clicking the button and the sound actually playing.
You can try a simplified code below which reproduces the "bug" very easily below:
$(document).ready(function() {
temp = new Audio("https://quemfazsite.com.br/temp/teclado/tons/102.mp3");
$("#play").on(
"click",
function() {
temp.currentTime = 0;
temp.play();
}
);
$("#stop").on(
"click",
function() {
temp.pause();
}
);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<div id="play">PLAY</div>
<div id="stop">STOP</div>
I also tried using an <audio> HTML element but the same delay happens. In the past I found a website very similar with what I am trying to build right now, and it played the sounds very smoothly, fast... but I cant find it anymore.
Do you have any idea what I can do to remove the delay that I am facing? I tried this code on 2 different notebooks running Windows 10 and also on and Android phone (samsung note). The delay is not in the audio file, I created each audio file using Audacity and I made sure there is absolutely no empty space at the beginning of each mp3 track.
And there is one more problem: sometimes when I click the PLAY button, there is some small noise which lasts no more than probably 50ms, is very very fast noise, and it shows up randomly... This same exactly problem happened on the 3 devices I tested. Any suggestion I could try my friends?

Related

YouTube Iframe API - video will sometimes not play via custom controls and instead, it refreshes the video

A bit of a strange one - I'm working with the YouTube iFrame API for the first time, building a skin for a customers site.
I've followed the code examples provided by Google/YouTube (https://developers.google.com/youtube/player_parameters?playerVersion=HTML5#IFrame_Player_API).
The issue is that when clicking the play button, which calls player.playVideo(), under some circumstances it will play, but mostly, it just appears to refresh the video with no errors logged in the console. The video will fade to black as if it was about to play, but instead it fades back to the video "poster" with the play button.
You can view the entire code here - https://codepen.io/james-morton/pen/BEZGvm
I've tried various different things such as instead of using:
function onYouTubePlayerAPIReady() {
.. I tried this as per other examples to no avail
window.onYouTubePlayerAPIReady = function() {
Again, to be clear, the controls sometimes works, and sometimes it doesnt - same machine, same browser, same video - I've tried other videos and the same result. It's really inconsistent as it sometimes works.
Any ideas?
Edit:
After further debugging using the below:
function onPlayerStateChange(event){
console.log('State Change: ' + event.data);
}
I can see that for when it doesn't load, the player's state has changed from -1 (Unstarted) to 3 (Buffering), and then back to -1 (Unstarted) when clicking the play button.
It turns out the issue appears to be with CodePen - having transferred all of the code to my own environment, it works flawlessly with no playback issues via the controls.
Having reviewed https://css-tricks.com/play-button-youtube-and-vimeo-api/ that use a very similar setup, the problem was easily replicated on CodePen, and comments (all the way back from 2014) describe the issues that I experienced.
Hopefully this will be useful to others that spot this.
This is a strange one! I didn't quite 'solve' it but I have some feedback. On running your code, at first I couldn't get it to play at all (by either the middle 'YT' play button or by the custom play button), but when I used your 'ff' button (when it hadn't yet started to play), there was obvious signs that it had being activated. I changed the z-index in the yt-player from 2 to -2 and then was able to use the middle button to start play. After the initial play, I had no problem using the custom buttoms (pause/play worked fine) - and I refreshed and tried it multiple times, each time with success.
The one big issue is starting the first video play with the custom play button. You could maybe autostart it (perhaps with a delay?) to circumvent having to use the middle button? I did inspect the widths of the buttons (to see if maybe padding / overlap) may be affecting the play button but didn't find anything. I did notice that when I played the video that it was rising slightly from it's initial position so I tweaked the css a tiny bit (only a very slight tweak). Here's my codepen link (It's not that different from yours..) I hope this helps .. if even a bit.

How to interact with Netflix Cadmium video player on the client?

I have a Netflix account and I have peeked under the hood at its video player running inside Google Chrome. Netflix calls its video player "Cadmium" and the javascript exposes all the functions and event handlers you might expect, such as play, stop, pause, mute, etc. I'm building a little Chrome extension that would enable me to call these Cadmium player function, but the hard part for me is figuring out how to create an instance of the player so I can start calling. The javascript is large, complex, and somewhat obscure. Once I can create an instance of that player, I'm thinking that making calls into the functions will be easy.
Here is a relevant chunk of js:
muteOn: function() {
this.savedVolume = this.getVolume(),
this.updateVolumeDisplay(0),
this.scrubber.updatePercent(0),
this.muted = !0,
this.videoPlayer.setMuted(this.muted)
}
In Chrome dev tools I can set a breakpoint inside that block, and execution hits the breakpoint when I click the Mute button on the netflix video player. The Netflix js is (unsurprisingly) heavily obfuscated via method renaming. I tried stepping through the code in the debugger and ended down a hundred rabbit holes, never able to find my way to the top of the stack, so that I could make that same call (at top of stack) to simulate the user clicking the mute button. I also tried the approach of programmatically clicking the mute button on the UI player, which would meet my needs equally well, but they have serious defensive mechanisms in there, spinning me like a top.
Since there are over 100K lines of javascript, and I'm uncertain which chunks exactly would be relevant for this post, I would like to suggest that you load Netflix in Chrome, open dev tools, play a movie, and inspect the pause or mute button. Interacting with those video player controls takes you into the maze of javascript which I'm trying to see how I can tap into to control aspects of the player programmatically (just from dev tools is fine for now). Another important thing I need to figure out is how to query the video player to determine the current elapsed time of the playing video.
Any ideas how I can crack this nut? (Thanks in advance!)
Using Chrome, I get playback using HTML 5 video.
Once you get a hold on the <video> tag element, you can use the HTML 5 video API:
Get the <video> element
var video = document.evaluate('//*[#id="70143639"]/video',document).iterateNext()
70143639 is the id of the video, as in https://www.netflix.com/watch/70143639
Remaining time (HH:mm)
document.evaluate('//*[#id="netflix-player"]/div[4]/section[1]/label', document).iterateNext().innerHTML
Elapsed time (seconds)
video.currentTime
Elapsed time updates
video.addEventListener("timeupdate",
function(e) {
console.debug("Seconds elapsed: ", e.timeStamp/1000/60);
}
);
Note that I don't get the same results as with video.currentTime, you may need to use an offset based on the difference. Also it may be something explained in the spec: https://www.w3.org/TR/html5/embedded-content-0.html
Play
video.play();
Pause
video.pause();
Go back and forth in time
Courtesy of rebelliard:
netflix.cadmium.UiEvents.events.resize[1].scope.events.drage‌​nd[1].handler(null, {value: 600, pointerEventData: {playing: false}}); where 600 is the number of seconds to seek.
Note that I ran into "Whoops, something went wrong..." using this:
video.currentTime += 60;
Even with pause and play calls. This is what this demo page does, you nay need to read the full spec on seeking.
Mute and get muted status
video.muted = true
Like video.currentTime, this is a writeable property.

How to increase audio loading speed using JavaScript?

I have created code for playing an .mp3 file using JavaScript. But the file is taking to much time to play on Android. I want to play the sound quickly after click on a text image. How do I increase loading speed on Android?
My JavaScript code:
if(window.audio)
{
audio.pause();
}
window.audio = new Audio (audio_path);
window.audio.play();
Check demo here -
http://97.74.195.122/gizmo-demo/canvasslidertwo.php
In the above link, click on the Japanese word for playing sound.
You are actually facing the bug depicted in this question. Which makes chrome browsers redownload the files from an Audio Element each time you change its src property (no-caching).
One solution would be to use the WebAudioAPIand store your audio files in the buffer. Doing so, you should be able to call them with no latency.
You can check the accepted answer for an example on how to deal with it.
Or you could also try not to call a new Audio() on each click, and rather load every audios from your page and only call their play() method on click.
But I'm not sure it would fix your issue.

Setting currentTime for HTML5 video on Android not working properly

I have created a set of custom navigation elements for a video, to simulate walking around a building (for fire training).
When an overlay is pressed, the routine jumps to a predetermined spot using vidElmt.currentTime = 5; (for example). This works fine on Windows (Chrome, FF, and IE 11) and on the iPad (Safari), but when I try it on my Android phone (4.3, using Chrome or the built-in browser), the videos jump to the wrong spots. For example, if I set it to jump to the 5 second spot, it looks like it jumps to 2, 3 or 4 second spot.
I know some people may point out that I could be trying to jump to a spot not yet loaded, but I know the parts of the video I'm jumping to are definitely already loaded.
I wonder if it's something about my video format (mp4). I've searched to see if anyone has problems with the video tag and currentTime on Android, but I'm not finding anything.
Here is my demo link, if you want to check it out for yourself: http://eqsim.com/fesim/ when the playhead arrives at side/location, it should loop that specific section, and you can press the arrow keys that are lit up to change locations.
I'd appreciate any suggestions!
-jonathan
I suspect you might need to keep querying the video in an interval until the frame you want is seekable. A full working example can be found in this jsbin, but the relevant code is this:
function isSeekable(time) {
for (var i=0; i<video.seekable.length; i++) {
if (video.currentTime > video.seekable.start(i) && video.currentTime < video.seekable.end(i)){
return true
}
}
return false
}
Does that work for you? It seems to work in my Android 4.3 stock browser. If not, can you tell me more about how you encoded your video? Adding more keyframes could help with frame accuracy.

Is there a way to get the progress of an mp3 download on the ipad?

We are developing a Javascript web app for the Ipad that requires sounds to be preloaded before it loads. We don't know what sounds the user needs until they click on an exercise and then they need multiple sounds to be preloaded before the exercise starts.
I am aware there is no preload method, and that the download needs to be bound to a direct tap / click event. We have spent a considerable amount of time trying many combinations of adding media elements dynamically on every click (loaded with dummy sounds) and then trying to swap them with the mp3's we need at the time.
We have given up on that approach and thought we could just join the sounds into one file and move the play head to the desired ranges (contained in a JSON file). We got this working successfully on the desktop but we can't do it on the Ipad because we don't know when the sound is completely downloaded.
Even after the user initiates the sound to be played, the device has no method for checking when the sound is fully downloaded. In fact, it doesn't download the whole file unless it is playing. What we have discovered is that we can not consistently get the duration unless the play head has reached the end in a linear fashion. We have tried to check the buffered.start() and buffered.end() properties against our own duration (we have the JSON file with all the times) but as soon as we try and set audioElement.currentTime and stopTime, it just plays the whole sound from beginning to end.
We have found that the seekable property to be unreliable as well.
We are now working with ios5 and I believe that older versions work differently in regards to the duration property.
Has anyone been able to get this working?

Categories