angular / angular.js

AngularJS - HTML enhanced for web apps!
https://angularjs.org
MIT License
58.82k stars 27.51k forks source link

ngSrc doesn't work properly with HTML5 Video Source tag #1352

Closed red-crown closed 9 years ago

red-crown commented 12 years ago

In firefox, ngSrc directive on video elements' tag doesn't work at all, and results in unsupported video format error. In chrome, updating ngSrc with data-binding doesn't update video, as it only loads video on page-load. i.e.

<video controls>
     <source ng-src="{{src}}">
</video>

doesn't work in Firefox at all, and in chrome it only works on first loading.

However,

<video ng-src="{{src}} controls></video>

works in both browsers, and it can be updated dynamically with no problems.

This is a problem, when having multiple video formats in order to support all browsers.

Related: #339

sourcec0de commented 11 years ago

Im having an issue as well, however I feel that the issue resides in Angulars ng-repeat. If i remove the video from that scope it plays fine, otherwise none of the controls will even load.

qaiser110 commented 11 years ago

me too! http://stackoverflow.com/questions/15728424/html5-video-is-not-working-with-angularjs-ng-src-tag

clong365 commented 11 years ago

me too.

gsk727 commented 11 years ago

me too! help me

Scottjutsu commented 11 years ago

+1

I'm using ng-repeat to set ng-src sources and they load correctly on page load, but if the video gets hidden via ng-show and then shown again the sources don't reload (in Chrome).

I can confirm sourcec0de's observation - if I remove the ng-repeat and use a single ng-src source (or multiple ng-src sources) the video reloads correctly upon re-showing.

hsdk123 commented 11 years ago

I'm having the same problem. Is anyone currently looking into this?

AutoSponge commented 11 years ago

With or without ng-src, with or without ng-repeat, chrome repeatedly fails to reload an HTML5 video after navigating away then coming back to the page.

From a clean cache, I see 2 requests (first one Pending), second with 206 Partial Content. If I refresh, I see one request with 304 Not Modified. When I navigate away from the video view then return (either through a link or using back button), I get two requests for the video with just a Pending status. One of these will have a mime-type video/mp4 (correct), the other just says Pending.

qaiser110 commented 11 years ago

Is anyone even looking at this issue???

petebacondarwin commented 11 years ago

Can you provide a running example of this issue? Does it work on some browsers at all? Have you checked whether browsers support changing the src attribute on HTML5 video elements after rendering?

AutoSponge commented 11 years ago

Sorry, the example app is not published yet. Works fine in Safari. As indicated above, I used both ng-src directive and a hard-coded src attribute with the same results.

petebacondarwin commented 11 years ago

What happens if you change the src with straight jQuery? I wonder if this is actually a bug in the browser rather than AngularJS?

On 16 July 2013 22:31, Paul Grenier notifications@github.com wrote:

Sorry, the example app is not published yet. Works fine in Safari. As indicated above, I used both ng-src directive and a hard-coded src attribute with the same results.

— Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/1352#issuecomment-21075654 .

AutoSponge commented 11 years ago

Even if I'm not changing the src (e.g., hard-code the video src attribute), the issue occurs. I don't have a way to simulate the problem away from Angular since Angular controls the content. I agree, it may be simply a problem in Chrome but I'm not sure how to test that.

petebacondarwin commented 11 years ago

What do you mean that Angular controls the content?

AutoSponge commented 11 years ago

The problem occurs when, using Angular's controller, the content changes, loading another view. Using the back button or a link to the previous route displays the former content but the video fails to load--every time. If it's an Angular issue, it's probably only in Chrome. My guess is that Chrome's aggressive caching and Angular's method for changing views can't agree on what should be loaded.

egamonal commented 11 years ago

@AutoSponge my test case was: page 1 with a button to go to page 2 page 2 with a videojs player and a button to go back to page 1

navigate to page 1, then to page 2, video is loaded correctly. click on button to go back to page 1, then go to page 2, google chrome stops using videojs. this happens because the videojs object was not removed when angular removed the element from the DOM, as expected. this isn't an angularjs (yay!)

Remove it before initializing the videojs player. I do this because I have a directive that adds a player. For example, if used in a directive:

... directive('mydir', ... {
    var vp;
    return {
        link: ..{ 
            if (vp) vp.dispose();
            vp = videojs("mp4video");
        }
    };`
AutoSponge commented 11 years ago

Just like the OP, I'm not using a wrapper object. The video is loaded through an HTML5 video tag. Are you suggesting that should be removed separately?

egamonal commented 11 years ago

well, videoJS keeps track of players added to the DOM but it looks like it is not watching changes. If you remove the element from the DOM (e.g. because you navigate to another route), videoJS won't know and it won't initialize it again. see line 17: https://github.com/videojs/video.js/blob/master/src/js/core.js if you remove it outside of videoJS, I guess you should call the dispose() method of the player. I guess this works like when you wrap a jquery plugin (?). This is what makes me think that it isn't an angular issue.

neoswf commented 11 years ago

having this problems as well. loading AV files to src or ng-src doesn`t do the job. need to write directives or factories for it to work. http://stackoverflow.com/questions/15485768/changing-html5s-source-src-attribute-takes-no-effect-wtih-angularjs

ghost commented 11 years ago

I'm having this problem as well.

Video fails to load in Chrome, Firefox and Safari. It works, however, in IE.

Here's a work around:http://stackoverflow.com/questions/15728424/html5-video-is-not-working-with-angularjs-ng-src-tag

It creates a messy flicker on page load, but it works.

mlegenhausen commented 10 years ago

+1

nihaopaul commented 10 years ago

a workaround is as follows:

in your controller set a function in my case is like this:

    $scope.play = function(who) {
        var name = who.id.split('.')[0];
        $scope.audio.mp3 = name + '.mp3';
        $scope.audio.ogg = name + '.ogg';
        $scope.audio.play = 'views/audio.html?'+name;
    };

then in my case in my template i had the following:

<div ng-include src="audio.play"></div>

my template in views/audio.html looks as follows:

<audio ng-model="audio" controls autoplay >
    <source ng-src="{{audio.mp3}}" type='audio/mp3'></source>
    <source ng-src="{{audio.ogg}}" type='audio/ogg'></source>
</audio>

if $scope.audio.play does not change then no reload will happen, so i'm using the name of the file, this could just be a random number instead

IgorMinar commented 10 years ago

@caitp I thought you had a PR for this, is my memory failing me?

caitp commented 10 years ago

@IgorMinar I was going to work on it, but I realized that I couldn't reproduce the problem (see http://jsfiddle.net/J77gE/). I thought it would be fun to build a media helper module instead outside of core with more binding options.

But as far as I can tell, ng-src works fine for source tags in modern browsers and modern angular

AutoSponge commented 10 years ago

The problem I mentioned was specifically due to changing views and using the back button. I'm not sure how that jsfiddle attempts to recreate the problem.

caitp commented 10 years ago

It doesn't, the point is that we don't have an issue interpolating the source tags, I think this is not the issue. I haven't been able to reproduce your particular issue at all

IgorMinar commented 10 years ago

@AutoSponge can you provide a demo app and instructions on how to reproduce this please?

AutoSponge commented 10 years ago

http://jsfiddle.net/AutoSponge/Yh9en/

Click the Video link. It will load the first time. Click Home and then Video again. Within 1 or 2 clicks it will probably stop loading in Chrome.

(and don't judge, I threw this together based on an app from 8 months ago!)

caitp commented 10 years ago

@AutoSponge this isn't an Angular problem. It's a weird behaviour of Chrome, but it is still interpolating your source file and getting the right src. It seems to be an issue with caching, which is a bit unfortunate. (you have this issue with ngIf as well, but this can be circumvented by using ngShow + setting the volume to 0)

AutoSponge commented 10 years ago

I agree it's an unfortunate issue with Chrome. I think that's the main reason this issue stayed open for 9 months with little work on it. Since Chrome is not likely to fix it, do you think it's unreasonable to create a cache-busting option? I'm thinking it would just append a random string to the src.

I also thought it might have something to do with pushState--either the implementation in Chrome or the use of it in Angular. But I honestly thought it would have been fixed by now.

caitp commented 10 years ago

I feel like this particular issue probably belongs on the chromium issue tracker (I think there are a couple of HTMLMediaElement cache-related issues already open, so it would be worth talking about it there).

I can't recall, but it's possible that this is the expected behaviour defined in the spec (and it wouldn't be the first time that the spec asked for weird/unfortunate behaviours)

um104 commented 10 years ago

This may be separate from the issue I've been having, but I had an issue where

Hope that was somewhat intelligible and related!

avvero commented 10 years ago

Just found out some workaround. It works for chrome, but not for another browsers (in some cases, time after time, etc) :) Last comment in http://stackoverflow.com/questions/16137381/html5-video-element-request-stay-pending-forever-on-chrome

um104 commented 10 years ago

As another note, the HTML5 spec notes that dynamically modifying the src attribute of a tag will have no effect, but doing the same on the src attribute of an

thirtythree commented 10 years ago

After a bit of googling I found that this is most probably related to chrome waiting for available sockets not to do angular, and that adding preload="none" to the video tag seemed to fix the issue.

agliottone commented 10 years ago

workaround

in controller

$scope.mp3 = "http://download.jw.org/audio.mp3"

$scope.$watch('mp3', function() {
       $("audio").attr("src",$scope.mp3)
   });

html:

<audio id="mejs" type="audio/mp3" controls="controls"></audio>
btford commented 10 years ago

@agliottone your suggested workaround uses bad practices. You should never be writing to the DOM from a controller like that. Consider using a custom directive.

agliottone commented 10 years ago

@btford I agree but.. Extremis malis, extrema remedia

msandeepraj211 commented 10 years ago

+1

binarykitchen commented 10 years ago

I think each time a new source has been set, you must call .load() on the native video element again to make the new video source show up.

jharaujoads commented 10 years ago

Hi I have a problem with angularJS on Google Chrome when I load the page in first time the HTML 5 Video load but when I change the view with ng-view it doesn't load but in firefox an internet explorer it's works very well.

I don't know what I have to do about it!

IgorMinar commented 10 years ago

This look like a similar issue to <embed> and ngSrc. See #339

phillip-haydon commented 10 years ago

This neeeeeeds to be fixedddddddd :(

kaiqigong commented 10 years ago

I have written a plnkr
click the video, the video loads. Click other link then back to video. The video is pending. You can see the requests in chrome network. Two request, one is the previous, still getting. Another is new one, pending.

phillip-haydon commented 10 years ago

@kaiqigong I got it working last week by setting the URL as trusted for the video since the video was not local to the website.

http://plnkr.co/edit/CL0Lh6VGMy0M3mR1SvVA?p=preview

I forked your plnkr and modified it to set the URL and trust it:

   .controller('VideoController', function($scope, $sce, $routeParams){
        $scope.name = "VideoController";
        $scope.params = {
          videoUrl: $sce.trustAsResourceUrl("http://www.videogular.com/assets/videos/videogular.mp4")
        };
   })

There's a delay on the video but it's working for me.

kaiqigong commented 10 years ago

@phillip-haydon thanks for you reply. I tried your plnkr, but it is still not working properly. (Try quickly switch between links.)
What I found is, when we remove the video tag(by changing route or some other DOM operations), the browser is still pulling the video source. When we switch back to the video. Another video request is made which makes the network traffic jammed. If I set the src of video to '' before removing the video tag, the browser will stop pulling, which solve the problem. Please try this codepen: http://codepen.io/cagegong/pen/bJHAz

So my final solution:

$scope.$on '$destroy', () ->
  angular.element('video').attr 'src', ''
phillip-haydon commented 10 years ago

Yeah mine works, just not 100%, why the browser doesn't kill the request itself when the dom element requesting it is destroyed I have no idea. I don't believe this is something Angular itself should be required to handle.

It's interesting to see that setting it to empty string does kill the request tho, I might have to setup something to add that in my project. Thanks.

kaiqigong commented 10 years ago

@jharaujoads Hope this solves your problem

alfonsomartinde commented 9 years ago

:+1:

IDontEatSoap commented 9 years ago

Wow, two years and nothing. Is angular being maintained at all?

phillip-haydon commented 9 years ago

Angular isn't worth the time and effort. They already said "fuck you" to the community with Angular 2.0.