Audio playing issues Angular - angularjs

I just started learning AngularJS and am facing an issue with audio playing. Here is part of my controller's code :
$scope.preview=function(id){
searchRequest.getSound(id).get().then(function(response){
var audio = $("#player");
$scope.link=response.data.preview;
audio[0].pause();
audio[0].load();
audio[0].oncanplaythrough = audio[0].play();
});
}
And HTML :
<audio controls id="player">
<source ng-src='{{link | trustUrl}}' type="audio/mp3">
</audio>
It is actually supposed to set the new song's url every time I click on a different item and play it (I am not sure designing it the right way according to Angular, as I told you I just began). When I click for the first time on a song, the data binding has been well done and the source url has been modified but the song doesn't get played. Then when I choose another item, it still sets the right url to the source but plays the previous one every time. Basically I need to click 2 times on a song to make it read.
Do you know how I could fix it ?
Thank you

$scope.preview=function(id){
searchRequest.getSound(id).get().then(function(response){
var audio = $("#player");
$scope.link=response.data.preview;
audio[0].src = response.data.preview;
audio[0].pause();
audio[0].load();
audio[0].oncanplaythrough = audio[0].play();
});
}
should work as expected

Related

Audio tags in React app play wrong audio clips when list of audio clips is filtered

I'm working on a simple react app that allows playback of a set of mp3 files using the HTML audio tag and filtering of the set of mp3 files to allow the user to find the ones they want to play.
It works fine when no filtering is applied and I see an Audio player for each mp3 file. But when I filter the list of mp3 files, I see a correctly reduced list of audio players but they do not always play the correct file now.
For example, if I have three mp3s - A, B and C - and then I filter to just show B and C I now see two audio players. But they will play A and B, not B and C. And in this case, as A is filtered out, I want the app to show audio elements for B and C that actually play B and C.
I've put together some code in a React sandbox that I hope shows the problem. If you filter the mp3s in the sample app to just show the ukulele sound clip, it still plays the first mp3 when you click the play button.
https://codesandbox.io/s/react-example-5y0bp?fontsize=14&hidenavigation=1&theme=dark
I've seen this behaviour now on Chrome, Firefox and Edge. Even on Chrome on iOS.
Any ideas what's going on here? Or how I can prevent or work around this? Am I just missing something glaringly obvious? Any advice welcome.
Thanks.
Currently your example application emits the following error: Warning: Each child in an array or iterator should have a unique "key" prop.. You would need to add a unique key to each item returned from Array.prototype.map(). This will help "React identify which items have changed, are added, or are removed" and in your situation ensure filtering can work effectively. In your case it looks like each URL is unique so perhaps that can be used as an effective key:
<div>
<h1>Filter</h1>
<input value={this.state.text} onChange={e => this.handleChange(e)} />
<ol>
{filteredList.map((item, index) => {
return (
<div key={item}>
{item} -{" "}
<audio controls preload="none">
<source src={item} type="audio/mpeg" />
</audio>
</div>
);
})}
</ol>
</div>
You can use index as a last resort key, but it is recommended to avoid using index as key. Otherwise you can use packages like uuid, Date methods such as getTime(), or even something extracted/combined from each url string value to create unique keys when you initialize state or add items to the state array.
Here is an example in action.

How can i switch the source for the VideoJS player?

I want to create a videoplayer in a browser, and be able to switch the source of the video.
All the video's are stored on the computer.
I am trying to use VideoJS, an i got it working for 1 video, but i cannot get it to switch to a different video.
I would like to open an video from a location, for instance using:
<input type="file" id="files">
This would be the source for the player.
The source of the videojs is as follows, where i cannot use a variable.
<source src="video/example.mp4" type='video/mp4'>
Anybody an idea?
I am fairly new to HTML5 and Javascript, and i don't know which termonolgy to use to find the answers.
First you get the instance of your player and then you set a new source (or new sources) via the Player.src function:
var player = videojs('my-player');
player.src({ type: "video/mp4", src: "http://www.example.com/path/to/video.mp4" });
For more detailed information, have a look at the documentation of Player.src.

ngaudio screen's click stops the audio

In AngularJs 1, when using the ngAudio service, and playing audio like this :
$scope.audio = ngAudio.load("abc.wav");
$scope.audio.play();
After the sound is played, a click on the screen stops it.
Why is that, and how can I change it ?
I'll appreciate your answers. Thanks
Try running ngAudio.setUnlock( false ); on the ngAudio service.
The culprit is on line 147 of angular.audio.js.

ng-srcset images initially not displaying in IE11 intermittently

The page loads without any of the images displaying on IE11 only, but refreshes them accordingly when we resize the browser intermittently (1/3 loads). We cannot replicate this with any of the other browsers. srcset works fine by itself with static content.
Here is a Plunker example of it not working in IE11.
Or quick and easy, the actual img html we're using:
<img data-ng-srcset="{{::image.url}}, {{::image.url2x}}" alt="{{::image.name}}"/>
The images or surrounding divs do not have any transitions, shadows or opacity applied.
The html renders fine with angular passing over and rewriting the srcset attribute correctly. The images just do not appear, only the alt tag. Wondering if this could be a call stack issue due to the intermittence of it, maybe a race condition with Picturefill loading before angular finishes a digest or something.
Cheers in advance!
A work around if you use PictureFill in a loop and in a specific case (not on all images of your application), is calling a function that launch PictureFill directly from HTML, after last item loaded (this is not the best practice but fix the IE11 problem) :
<picture><!-- Your image --></picture>
<span ng-if="$last">
{{ controllerAlias.launchPictureFill() }}
</span>
Came across this as a solution: http://tech.endeepak.com/blog/2014/05/03/waiting-for-angularjs-digest-cycle/
var waitForRenderAndDoSomething = function() {
if($http.pendingRequests.length > 0) {
$timeout(waitForRenderAndDoSomething); // Wait for all templates to be loaded
} else {
$window.picturefill();
}
}
$timeout(waitForRenderAndDoSomething);
The only issue that the blog post describes is here, so if anyone has anything better please let me know:
The $http.pendingRequests supposed to be used for debugging purpose only. If angular team decides to remove this, you can implement the same using http interceptors as suggested in this link.

AngularJS - HTML5 video is loading multiple times

I have an AngularJS app that presents some sequential videos and if I go to another URL (by using another HTML reference, href) the old controller stays active and both videos still playing. This happens for each new page with the same controller that I've openned, creating multiple video instances.
The controller receives a video SRC and sets it using ng-src.
EDIT
I am getting video element by ID:
var video = document.getElementById("video");
And setting correspondent source when controller is initialized:
if (video) {
video.src = Modernizr.video.ogg ? $scope.mainVideoUrlogv :
Modernizr.video.webm ? $scope.mainVideoUrlwebm :
$scope.mainVideoUrlmp;
$scope.playVideo();
}
HTML
<video id="video" ng-mouseup="pauseOrPlayVideo()">
<source ng-src="{{mainVideoUrlwebm}}" type="video/webm">
<source ng-src="{{mainVideoUrlogv}}" type="video/ogv">
<source ng-src="{{mainVideoUrlmp}}" type="video/mp4">
</video>
The solution was to remove the video Element from the page.
var video = document.getElementById("video");
Mozila documentation about ChildNode.remove() helped to perform remove action.
video.remove(); //javascript way
However, I've realized that it does not work on IE, as you can notice in the last reference.
The solution was to perform this action in jQuery.
$('video').remove(); //jQuery way
It works in the browsers that I have tested, namely Chrome, Firefox Dev Edition and IE9, IE10.

Resources