Erstellen der interaktiven Funktionalität von Vyclone mit HTML5
Erstellen der interaktiven Funktionalität von Vyclone mit HTML5
Im Zuge der zunehmenden Verwendung von HTML5 durch Entwickler wird das Web für Benutzer interessanter und produktiver. In diesem Gastbeitrag berichtet Anton Molleda von Plain Concepts über seine Erfahrungen beim Entwickeln von Vcylone, einer sozialen Videoschnittanwendung auf Basis von HTML5 und anderen der vielen neuen Features von Browsern der nächsten Generation wie Internet Explorer 10. Vcyclone baut auf Funktionen wie Zeigerereignissen, Mehrfingereingabe und hardwarebeschleunigtem Canvas und CSS3 auf, um diese Website wie eine App wirken zu lassen.
– Rob Mauceri, Group Program Manager, Internet Explorer
Hallo,
mein Name ist Anton Molleda, ich arbeite bei Plain Concepts. In den letzten Monaten hat das Internet Explorer-Team mit der großartigen Gruppe zusammengearbeitet, die für das aufregende neue soziale Videostartup Vyclone zuständig ist. Als Webentwickler gehört es zu meinen schönsten Momenten, wenn sich die Gelegenheit bietet, neue Möglichkeiten im Web zu entdecken. Glücklicherweise durfte ich bei diesem Projekt mitarbeiten. Heute möchte ich mit Ihnen gerne ein paar der wesentlichen Erfahrungen teilen, die wir bei der gemeinsamen Arbeit an einem webbasierten Video-Editor für Vyclone gemacht haben – ausschließlich mit HTML5 und JavaScript!
Vyclone ist eine gemeinschaftliche Videoplattform, auf der zusammen mit anderen Anwendern mühelos verschiedene Videos erstellt, synchronisiert und bearbeitet werden können.
Beim ursprünglichen Start war Vyclone ausschließlich für mobile Geräte gedacht. Schon schnell stellte sich heraus, dass die Aufnahmemöglichkeiten auf einem Smartphone zwar optimal sind, das Bearbeiten von Videos jedoch durch Bildschirmgröße und Geräteleistung eingeschränkt ist. Da sich moderne Browser in den letzten Jahren erheblich entwickelt haben, stellte HTML5 einen geeigneten technischen Ansatz zum Erstellen dieses neuen Tools dar.
Im Wesentlichen besteht der webbasierte Vyclone-Editor aus drei Komponenten:
Die Videovorschau: Auf der linken Seite kann das aktuell geschnittene Video in niedriger Qualität wiedergegeben werden.
Das Videoraster: Im rechten Bildschirmbereich werden dem Benutzer alle verfügbaren Quellen angezeigt, einschließlich Position und Zeitpunkt.
Die Timeline: Die Timeline bietet eine lineare Sicht der einzelnen Quellen, aus denen sich das Video zusammensetzt. Eine in einem bestimmten Zeitabschnitt wiedergegebene Quelle wird als „Cut“ bezeichnet (angezeigt über den Playersteuerelementen)
Wenn ein Benutzer das Video wiedergibt und der Timeline neue Cuts hinzufügt, wird die Videovorschau automatisch angepasst. Im Videoraster wird die Quelldatei als Hinweis auf das ausgewählte Video durch Dreiecke visuell hervorgehoben.
Beim Umsetzen dieser Funktionen begegneten wir durch den bloßen Umfang der Videobearbeitung einer interessanten Herausforderung in Bezug auf die erzielbare Leistung und die Benutzerfreundlichkeit. Lassen Sie uns näher betrachten, wie wir dies im Web möglich machten. Wir verwendeten Video, Canvas und requestAnimationFrame (RAF). Im Hintergrund wird ein Video wiedergegeben und in jedem RAF die aktive Quelle in einem Canvas (in der Videovorschau) dargestellt bzw. die neue Größe und Position im Videoraster berechnet.
So weit, so gut: Was aber geschieht, wenn der Benutzer mit diesen Inhalten interagiert? Was passiert beispielsweise, wenn der Benutzer die Timeline vorwärts oder rückwärts bewegt oder Videoquellen (Cuts) hinzufügt oder entfernt? Beim Erstellen der ersten Prototypen verfolgten wir als Standardansatz, auf die Auslösung des jeweiligen Ereignisses zu warten – so haben wir es schließlich gelernt, oder?
Was passiert aber, wenn diese Ereignisse pro Sekunde dutzendfach oder sogar hunderte Male ausgelöst werden? Und was passiert, wenn die Benutzeroberfläche von den entsprechenden Handlern aktualisiert werden muss? Muss der Bildschirm tatsächlich 130 Mal pro Sekunde aktualisiert werden, wenn die Deltaänderung möglicherweise nicht einmal einen Pixel ausmacht? Was für eine Leistungsverschwendung!
Wenn Ihr Computer über einen i7 und 8 GB RAM verfügt, verfügen Sie wahrscheinlich über die erforderliche Rechenleistung. Was aber ist mit Benutzern, die ältere Hardware oder ein ARM-Gerät haben? Diese Anwender werden wohl nicht die gleichen Erfahrungen machen, sondern eher eine sehr langsame Website erleben.
Im ersten Ansatz dachten wir an das Einbringen der RAF-Aktionen in eine Warteschlange. Es gab hierbei jedoch einige Probleme, beispielsweise bei identischen RAF-Funktionen im gleichen „Tick“, was die Dinge nur verschlimmert. Zum Umgehen dieses Problems verwendeten wir zunächst eine Variable zum Ermitteln, ob sich eine Aktion bereits in der Warteschlange befindet. Ungefähr so:
var queued = false; function myAction(){ //your awesome code here queued = false; } function onEvent(evt){ if(!queued){ queued = true; requestAnimationFrame(myAction); } }
Dieser Code ist nicht schlecht, birgt jedoch weiterhin einige Probleme. Wenn Sie etwas mit Bezug auf die Ereignisposition (Maus oder Zeiger) und einem Delta entwickeln möchten, ist dieser Ansatz möglicherweise nicht optimal. Die von uns in der Timeline verwendete Lösung besteht im Sammeln der Ereigniswerte und Verarbeiten in myAction:
var deltaX = 0, queued = false; function myAction(){ //your awesome code here uses deltaX deltaX = 0; // we reset the deltaX so it can be incremented // next time onEvent is executed queued = false; } function onEvent(evt){ if(!queued){ queued = true; deltaX = evt.translationX; // in the case of a pointer, if you are // using a mouse you will have to do some // magic with pageX or similar :) requestAnimationFrame(myAction); }else{ deltaX += evt.translationX; } }
Mit diesem Ansatz ließen sich die erläuterten Herausforderungen bewältigen. Wir fügten weitere Funktionen hinzu, bis ein paar neue Probleme auftauchten.
Durch die angemessene Verarbeitung dieser Ereignisse für jeden requestAnimationFrame waren wir in der Lage, eine bessere Reaktionsfähigkeit ohne Einbußen bei der Rechenleistung zu erreichen. Da jedoch requestAnimationFrame alle Funktionen in der Reihenfolge der Warteschlange ausführt, wurde gelegentlich vor dem Säubern schon gezeichnet oder die Timeline unnötigerweise verschoben. Wir mussten eine Menge an sperrigem Code schreiben, um sicherzustellen, dass die Ausführung in der gewünschten Reihenfolge erfolgt.
Wir erkannten, dass unser Code nicht optimal war; einige Zyklen gingen durch das Warten auf die Durchführung anderer Aktionen verloren. Wir entschieden uns daher, die Verarbeitungsweise des Inputs erneut zu ändern. In diesem Moment fühlten wir uns an eine Spieleschleife erinnert. Wenn Sie sich mit (einfacher) Spielearchitektur nicht so gut auskennen: Eine Spieleschleife (Game-Loop) besteht grundsätzlich aus einer andauernden Wiederholung, die unabhängig von Benutzerinteraktionen ausgeführt und beim Auftreten verschiedener Ereignisse und Aktionen abgetrennt wird. Laut dem Wikipedia-Artikel Spieleprogrammierung kann eine vereinfachte Spieleschleife in Pseudocode so aussehen:
while( user doesn't exit ) check for user input run AI move enemies resolve collisions draw graphics play sounds end while
Genau das brauchten wir. Auf Basis von RAF erstellten wir eine Tick-Funktion, die kontinuierlich ausgeführt wird und in der wir anhand der vorherigen Benutzereingabe oder anderen Faktoren die Folgeaktion bestimmen können.
Die vereinfachte Tick-Funktion für das Videoraster sieht so aus:
function tick(){ //we clean if we've changed the size of the quadrant if(needsClean){ cleanCanvas(); } // if we have to change the quadrant's frame because we are // the active one (or the opposite) if(newFrame){ drawFrame(); // we draw just the frame in a separate canvas so it // doesn't need to be calculated all the time, and it // is still faster than copying from an image } //we draw the new frame if we are playing or seeking if(dirty){ draw(); drawFrameInQuadrant(); } requestAnimationFrame(tick); }
Die Werte für needsClean, newFrame und dirty werden in den Ereignishandlern aktualisiert, wenn der Benutzer etwas sucht, ein Video wiedergibt oder ähnliche Aktionen durchführt.
Diese Veränderung des Blickwinkels auf Benutzerinteraktionen und der Wechsel zur Game-Loop ermöglichte größere Leistung und gleichzeitig einfacheren Code.
Großartige Erkenntnisse für Projekte, bei denen ein hohes Maß an Interaktivität und Benutzereingabe eine Rolle spielt. Denken Sie bei Ihrem nächsten Projekt an eine Game-Loop, die vielleicht alles ganz einfach macht! Bei uns hat es auf jeden Fall geklappt. Wenn Sie bisher noch keine Gelegenheit hatten, sich den neuen webbasierten Editor von Vyclone anzusehen, sollten Sie das dringend nachholen. Sie können den Editor aufrufen, indem Sie auf Vyclone.com bei einem beliebigen Video auf „Remix“ klicken. Ob Maus oder Fingereingabe, beides funktioniert sehr gut. Ich empfehle Ihnen besonders, es auf einem Surface Pro auszuprobieren!
Viel Spaß! Wenn Sie weitere Fragen haben, können Sie diese gerne in den folgenden Kommentaren stellen.
– Anton Molleda, Plain Concepts