Unable to find plugin: videoJsResolutionSwitcher i

2019-09-06 16:12发布

问题:

In the first implementation, I used angular2 without server rendering for creating a web player with video.js library and it's "videojs-resolution-switcher" plugin.

I created a directive for initializing videojs element based on component ngOnInitView and load js files directly in base html file (end of body).

Everything was correct and player worked as expected.

Then I started to setting up angular2-universal and server rendering. There was some problems about using browser specific features that I handled them with "isBrowser" tool.

But now I have a problem with videojs-resolution-switcher. Even with old configs in browser's console the error is:

Unable to find plugin: videoJsResolutionSwitcher
this.updateSrc is not a function
TypeError: this.updateSrc is not a function
at Player.<anonymous> (http://localhost:3000/main.bundle.js:95154:22)
at Player.<anonymous> (http://localhost:3000/main.bundle.js:5555:14)
at Array.forEach (native)
at Player.<anonymous> (http://localhost:3000/main.bundle.js:5554:20)
at bound (http://localhost:3000/main.bundle.js:8285:15)
at ZoneDelegate.invokeTask (http://localhost:3000/main.bundle.js:128033:31)
at Object.onInvokeTask (http://localhost:3000/main.bundle.js:38985:37)
at ZoneDelegate.invokeTask (http://localhost:3000/main.bundle.js:128032:36)
at Zone.runTask (http://localhost:3000/main.bundle.js:127836:47)
at ZoneTask.invoke (http://localhost:3000/main.bundle.js:128086:38)
at data.args.(anonymous function) (http://localhost:3000/main.bundle.js:129197:25)

I tried to require the videoJsResolutionSwitcher in directive, but it returns empty object (because it's not exported). Then I changed the plugin code to export the function but nothings changed just the error about updateSrc function was resolved.

I tried to import js file like this:

import '../../node_modules/videojs-resolution-switcher/lib/videojs-resolution-switcher.js';

But at the compile time an error raised about "undefining window" in videojs resolution switcher code.

videojs.ts directive:

import { Component, Directive, ElementRef, Input, Output, EventEmitter } from '@angular/core';
import { Subject } from 'rxjs/Rx';
let videojs = require('video.js');
import { isBrowser } from "angular2-universal";

@Component({
    selector: '[hiVideoJs]',
    host: {
        class: 'video-js vjs-default-skin vjs-big-play-centered',
        '[attr.poster]': 'poster'
    },
     template: ``
})
export class VideoJsDirective {
    @Input()
    private col;
    @Input()
    private poster;
    @Input()
    private sources: Array<string> = new Array<string>();
    @Input()
    private options: any = {};
    @Input()
    private mute: boolean = false;
    @Input()
    private endEvent: Subject<boolean>;

    @Output()
    private fullscreen: EventEmitter<{}> = new EventEmitter();

    @Output()
    private created: EventEmitter<{}> = new EventEmitter();


    constructor(private element: ElementRef) {

    }

    ngAfterViewInit() {
        // require('videojs-resolution-switcher')();
        let width;
        if (isBrowser)
            width = this.col.clientWidth - ($(this.col).outerWidth() -     $(this.col).width());
        else
            width = this.col.clientWidth;
        var that = this;
        this.options.width = width;
        this.options.nativeControlsForTouch = false;
        this.options.plugins = {
            videoJsResolutionSwitcher: {
                default: 'high',
                dynamicLabel: true
            }
        };
        var that = this;
        if (isBrowser) {
            let player = videojs(this.element.nativeElement, this.options,     function () {
                this.updateSrc(that.sources);
                this.muted(that.mute);
                if (that.endEvent)
                    this.on('ended', a => {
                        that.endEvent.next(true);
                    });
                this.controlBar.fullscreenToggle.on('click', a => {
                    that.fullscreen.emit(true);
                });
                this.controlBar.fullscreenToggle.on('touchstart', a => {
                    that.fullscreen.emit(true);
                });
            });
            this.created.emit(player);
        }
    }

    ngOnDestroy() {
        console.log('destroyed');
        videojs(this.element.nativeElement).dispose();
    }
}

UPDATE

After a lot of testing scenarios, I solved this issue with removing "let videojs = require('videojs');" and adding this custom typings definition:

interface VideoJSStatic {
    (id: any, options?: any, ready?: () => void): any;
}
declare var videojs:VideoJSStatic;

But I'm looking to know conceptually, what was the reason of this behavior?