Nehmen Sie Kontakt mit mir auf:
 










Fragen?

Martin Gamnitzer

 

HD-Button für den HTML5-Videoplayer „VideoJS“

Jump to english version.

VideoJS gehört zur Gruppe der modernen JavaScript-Videoplayer, welche die HTML5-Funktionen zur Videowiedergabe nutzen und erweitern.
Bisher habe ich aber noch keinen Player finden können, der einen Wechsel der Videoqualität erlaubt, wie man das bspw. von Vimeo oder Youtube kennt. Scheinbar wird diese Funktion aber von vielen vermisst (zumindest wurde das Problem mehrfach an mich herangetragen), sodass ich mich hingestetzt und eine passende Erweiterung geschrieben habe.
Ich habe mich für VideoJS als Grundlage entschieden, da der Code sehr übersichtlich geschrieben ist und sich gut erweitern lies. Das Prinzip dürfte aber auch auf andere HTML5-Player übertragbar sein.

Zwar gibt es bereits einen HD-Switch für VideoJS, diese Lösung finde ich jedoch nicht zufriedenstellend, da das Video dort in einem iFrame geladen und beim Wechsel zu HD der ganze Frame neu geladen wird. Das funktioniert, ist aber nicht hübsch.

Hier geht’s zur Demo.

Benutzung

1. Vorbereiten der Videos

Für jeden Codec werden offensichtlich zwei Videos in unterschiedlichen Qualitäten benötigt. Bei der Benennung ist zu beachten, dass sich die HD-Version von der normalen durch ein Suffix unterscheiden muss. Das Suffix lautet „_hd“, lässt sich per Konfiguration aber auch ändern.
Ein Beispiel: Das Standard-Video heißt „einFilm.ogv“. Daraus ergibt sich für die HD-Version der Name „einFilm_hd.ogv“. Außerdem müssen die Videos im selben Ordner liegen.

2. Einbinden der Erweiterung

Die Erweiterung besteht aus einer Javascript- und einer Stylesheet-Datei, die NACH den VideoJS-Dateien eingeunden werden müssen. Das sollte dann in etwa so aussehen:

1
2
3
4
5
6
7
8
<head>
  <!-- [...] -->
  <script src="video.js" type="text/javascript" charset="utf-8"></script>
  <script src="videojs-hdswitch.js" type="text/javascript" charset="utf-8"></script>
  <link rel="stylesheet" href="video-js.css" type="text/css" media="screen" title="Video JS" charset="utf-8">
  <link rel="stylesheet" href="videojs-hdswitch.css" type="text/css" media="screen" title="Video JS" charset="utf-8">
  <!-- [...] -->
</head>

3. Startskript

Das funktioniert wie immer bei VideoJS, zusätzlich kann man aber mit der Option „hdSuffix“ ein anderes Suffix defnieren:

1
2
3
4
5
<script type="text/javascript" charset="utf-8">
  VideoJS.setupAllWhenReady({
    hdSuffix: "_high-def"
  });
</script>

4. Einbinden der Videos

Hier gibt es keinen Unterschied zum normalen VideoJS, da die Namen der HD-Videos per Javascript über das definierte Suffix ermittelt werden.

Das war’s – mehr gibt es nicht zu tun.

 

Funktionsweise und Codediskussion

Die Video-Implementierung in HTML 5 erlaubt es, mehrere Videos mit unterschiedlichen Codecs einzubinden. So kann sich jeder Browser das Video suchen, welches ihm am Besten gefällt. Gibt man aber mehrere Videos mit gleichem Codec an, nimmt der Browser das erste und ignoriert den Rest. Um nun mehere Videos (in unterschiedlicher Qualität) einzubinden, müssten wir noch eine zweite Datei angeben (je Codec) und dann per Javascript umschalten. Dabei sind mir zwei praktikable Lösungen in den Sinn gekommen:

  1. Innerhalb des Video-Tags gibt es außer den Source-Tags noch ein weiteres (zum Beispiel “div”), das widerum die source-Tags der HD-Version enthält. Also in der Art:
    1
    2
    3
    4
    5
    6
    
    <video>
      <source src="meinVideo.ogv" type='video/ogg; codecs="theora, vorbis"'>
      <div>
        <source src="meinVideo-HD.ogv" type='video/ogg; codecs="theora, vorbis"'>
      </div>
    </video>
  2. Die Videos folgen einem Benennungsschema, wodurch sich der Name der HD-Version automatisch ergibt, zum Beispiel durch Anfügen eines Suffix, wie ich es im eben gezeigten Codeschnipsel bereits eingebaut habe.

Wie oben bereits erwläutert, habe mich für die zweite Variante entschieden. Diese entpricht meinem bevorzugten Programmierstil „convention over configuration“ besser.

Damit war es „nur“ nötig, einen weiteren Button im Player zu platzieren und beim Klick darauf das entrechende Video zu laden. Werfen wir einen Blick auf das Javascript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
VideoJS.prototype.oldControlBar = VideoJS.prototype.buildControlBar;
VideoJS.prototype.buildControlBar = function() {
    this.oldControlBar();
    this.hdControl = _V_.createElement("li", { className: "vjs-hd-control vjs-sd", innerHTML: "<span>HD</span>" });
    this.controls.appendChild(this.hdControl);
    this.hdControl.addEventListener("click", this.onHdControlClick.context(this), false);
	if(typeof this.options.hdSuffix == "undefined")
		this.options.hdSuffix ="_hd";
}
 
// listen to clicks on HD button
VideoJS.prototype.onHdControlClick = function(event){
    if (!this.videoIsHd) {
        var isPause = this.video.paused;
        this.videoIsHd = true;
        this.hdControl.className = "vjs-hd-control vjs-hd";
        if(typeof this.sdSrc == "undefined")
        {
            this.sdSrc = this.video.currentSrc;
            this.hdSrc = this.sdSrc.slice(0,this.sdSrc.length-4) + this.options.hdSuffix + this.sdSrc.slice(this.sdSrc.length-4);
        }
        this.video.src = this.hdSrc;
    } else {
        this.videoIsHd = false;
        this.hdControl.className = "vjs-hd-control vjs-sd";
        this.video.src = this.sdSrc;
    }
 
    //copy status (play,pause)
    this.video.load();
    if (isPause) {
        this.onPause();
    } else {
       this.video.play();
    }
 
}

Um den HD-Button einzubauen, muss man die Funktion “buildControlBar” erweitern. Das geht in Javascript sehr einfach: Man speichert die alte Funktion in einer Variable (Zeile 1), definiert die Funktion neu (Zeile 2), ruft die in der Variable gespeicherte Funktion wieder auf (Zeile 3) und fügt seinen neuen Code an.

Dann muss für das Klick-Event noch eine Funktion angelegt werden (Zeile 12 ff.). Wenn man den Button das erste Mal anklickt, wird der Dateiname des Standard-Videos gespeichert und der neue Name ermittelt (Zeilen 17-21). Klickt man nochmal (und wechselt damit zum Standard-Video) wird der ursprüngliche Dateiname ausgelesen und an das video-Objekt übergeben.

Nachdem die Videoquelle festgelegt wurde, muss das Video geladen werden (Zeile 30). Zum Abschluss wird noch dafür gesorgt, dass der vorherige Abspielzustand (Play/Pause) wieder aufgenommen wird.

 

Nun noch die neuen Stylesheets:

1
2
3
4
5
6
7
8
9
10
/* change position and width of standard control elements */
.video-js-box ul.vjs-controls {padding-right: 196px;}
ul.vjs-controls > li.vjs-time-control       { width: 75px; right: 121px; }
ul.vjs-controls > li.vjs-volume-control     { width: 50px; right: 66px; }
ul.vjs-controls > li.vjs-fullscreen-control { width: 25px; right: 36px; }
/* add new stylesheets for HD-Button */
.vjs-hd-control{right:3px;line-height:32px;padding-right:4px!important;font-size:11px;cursor:pointer;}
.vjs-hd-control span{display:block;width:20px;height:12px;float:left;color:#fff;margin-top:-3px;font-weight:bold;font-size:12px; margin-left:5px;}
.vjs-hd-control span{color:#808080; font-family:sans-serif;}
.vjs-hd-control span:hover, .vjs-hd-control.vjs-hd span {color:#0066ff;}

Da der HD-Button nach rechts außen soll, wird der Ladebalken verkürzt und die Bereiche für Lautstärke und Fullscreen nach links verschoben.
Im zweiten Teil wird der HD-Button definiert und positioniert. Im HD-Modus und beim Darüberfahren mit der Maus spendieren wir ihm noch eine andere Textfarbe. Und das war es dann auch schon.

 

HD Switch in VideoJS

HTML5 gives us the chance to watch videos in a browser without using flash. By now, several javascript based players are build around these functionalities in order to add new features and skins. Sadly, non of them offers a hd switch, like the ones we know from Vimeo or Youtube. Many developers seem to miss this, so I tried to extend an existing player.
I choose VideoJS, because it’s code is very readable and relatively easy to extend.

I should mention that one hd switch for VideoJS is already existing, but I’m not satisfied with this implementation. There, the player is wrapped in an iFrame. By clicking the hd switch, the whole iFrame will be reloaded with another video source. It works, but it’s not neat.

Watch a sample.

 

Usage

1. Prepare the videos

Evidently we need two videos for every codec, one in standard and one in hd quality. The hd video must have the same name as the the standard video plus a suffix (default is “_hd”). Let’s say our video is called “aGreatFilm.ogv”, the hd version must be named “aGreatFilm_hd.ogv”.
You can define another suffix in the VideoJS configuration.

2. Include the files

The extensions consists of two files, one javascript and one stylesheet file. They must be included after the the VideoJS files. It should look like this:

1
2
3
4
5
6
7
8
<head>
  <!-- [...] -->
  <script src="video.js" type="text/javascript" charset="utf-8"></script>
  <script src="videojs-hdswitch.js" type="text/javascript" charset="utf-8"></script>
  <link rel="stylesheet" href="video-js.css" type="text/css" media="screen" title="Video JS" charset="utf-8">
  <link rel="stylesheet" href="videojs-hdswitch.css" type="text/css" media="screen" title="Video JS" charset="utf-8">
  <!-- [...] -->
</head>

3. Activate the script

You don’t need to do anything here, but you may define another suffix like this:

1
2
3
4
5
<script type="text/javascript" charset="utf-8">
  VideoJS.setupAllWhenReady({
    hdSuffix: "_high-def"
  });
</script>

4. Write the HTML part

You can use the normal HTML5 code here because the hd videos will be selected automatically.

 

That’s it!

 

 

Probleme? Anregungen? Lob? Immer her damit!

5 Kommentare zu “HD-Button für den HTML5-Videoplayer „VideoJS“”

  1. nitech sagt:

    Gretings friend. Thanks for the nice code and for posting in english too.

    Vielen dank.

  2. enzet sagt:

    Nur das Vollbild ist kein echtes Vollbild, bei Videojs ist es anders gelöst kann man das noch ändern?

    • martin sagt:

      Der Artikel ist vom 15.11.2010! Der Vollbildmodus entspricht dem der damaligen VideoJS-Version. In dem aufgeführten Code fasse ich den Vollbildmodus gar nicht an.

      Und ich bezweifle, dass sich die hier gezeigte HD-Lösung 1:1 auf den aktuellen Player übertragen lässt.

  3. enzet sagt:

    Danke für die schnelle Antwort!

  4. Felix Schwarz sagt:

    I would like to mention that this code does not work anymore with the current JW Player. I wrote a new extension, very basic but it works for me: https://bitbucket.org/felixschwarz/videojs-hdtoggle/