Dynamic Video Tag and Knockout JS

2019-05-07 20:01发布

问题:

I'm trying to dynamically change the video source of a video tag using Knockout. This is the code:

<div data-bind="if: resource().encodingformats() != ''">
    <video style="max-width: 100%;" controls>
        <!-- ko with: resource() -->
        <source data-bind="attr:{ src: webmUrl }" type='video/webm; codecs="vp8, vorbis"'>
        <source data-bind="attr:{ src: oggUrl }" type='video/ogg; codecs="theora, vorbis"'>
        <source data-bind="attr:{ src: mp4Url }" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
        <!-- /ko -->
    </video>
</div>

I'm using an if binding to make sure that a brand new video tag is rendered whenever the current resource is changed.

This works in all browsers except Firefox. Firefox gives me an error (warning, actually) of

<source> element has no "src" attribute. Media resource load failed.

I'm guessing the source element is getting rendered for a split second without the src attribute set, which is causing it to bomb?

Is there an easy way to fix this? I suppose I could just bind the entire video's html, but that seems overly sloppy. Is there an easy way to get Firefox to work with the same code that otherwise works fine in IE9?


EDIT

I should also mention that after using Firebug to look at the html generated, I coped the entire source tags into my code, and that worked fine. In other words, I ditched the knockout bindings for a minute, and copied in the html that knockout was generating, and everything worked.

The problem most certainly is that Firefox is extremely picky about how the source tags are generated.

回答1:

It turns out the real problem above is that Firefox fires off the "error" event even when there's no error.

So, if you're subscribing to this event so that you can fall back to a flash player for IE8 users, be sure to check your "error" handler to make sure there's actually an error.

$(videoTag).one("error", function(){
    //sometimes Firefox fires this event even though there's no error :-/
    if (!this.error) return;

Once you do that, Firefox should happily let you bind the video tag's sources as I did above.



回答2:

Seems like it would be similar to this: Controlling Flash Plugins with Knockout.js, Conflicting jQuery.tmpl and Knockout-Sortable.

Not very elegant, but the easiest solution is to use the html binding with a string that includes your elements. This ensures that there will never be a source tag that does not include a src attribute.

A better choice might be to whip up a custom binding that takes in a resource, creates a string containing all of the "source" tags, and then applies the html binding to the container element (or uses something like jQuery to append the elements). That would be a more elegant solution. Might need to generate the entire video tag, not sure how picky FF is about it.