PLAYER SPRING '17
Front & Back Again, a developer's tale by Chris & Eric
Everyone WATCHES our videos .
They should.
They're real good.
Content is king... but the castle is crowded.
The audience is discerning. Particularly millennials.
So even with the safest precautions,
embed behaviors,
in real life...
Are highly unpredictable.
You're not sure who is watching your content.
All while trying to stand out from a crowd.
So you do your research to keep up with best practices, trends, and metrics.
Or where.
THE FLOW
Proposed Implementation
to A/B Test titles & thumbnails on live videos in real time.
to strategically capture an audience, without hazarding editorial control or the creative integrity of the brands.
to find the Conde Nast voice that best resonates in that moment... not create more clickbait.
We want:
Player Architecture
(Rx & video.js)
RxJS
RxJS is a Javascript library ideal for dealing with highly asynchronous code.
It provides a way to model time, so that you can think of an event in your application as a function of other events, rather than state flags.
The fact that a video player is nothing but a continuous stream of disparate events (time updates, player notifications, load requests, user interaction, to name a few) makes it a good candidate for RxJS.
Resources
-
EggHead IO Rx Courses
https://egghead.io/technologies/rx -
RxJS Workshop at MLOC.js hosted by André Staltz
https://github.com/staltz/rxjs-training
http://andre.staltz.com -
ReactiveX IO's Learn Rx
http://reactivex.io/learnrx/
Shortest RxJS crash course of all time
Key data types are Observables & Subscribers.
Subscribers must provide at least one of the following three methods for notifications: next(), complete(), error().
Subscribers opt into these notifications by passing itself to .subscribe() on an Observable instance.
Observables
Subscribers
Shortest RxJS crash course of all time (pt. 2)
By convention, we always append a $ to the names of Observable instances.
Observables:
- Are always based on some kind of 'producer' (mouse click, Promise, WebSocket, video.js event...).
- Emit zero or more events. A collection of Observable events over time is called a stream.
- Provide operators for composition.
Through a series of compositions, you can transform producer events into a stream of events that are meaningful to your application
Model-View-Intent
Nothing to do with MVC.
Traditional model deals with modeling data.
Our model deals with modeling events.
Is similar to the 'data down, actions up'
mantra of React.
PlayerFacade
Client-facing API for the player.
As the name implies, this is a middle-man designed to prevent clients from directly accessing our player.
Includes setters: play(), pause(), volume(), load(), setNextVideo()
& getters: currentTime(), currentVideo(), duration(), isPlaying(), volume() (again).
Leverages RxJS Subjects, which are a special kind of Observable that don't require a producer.
Instead we manually push events onto it at the appropriate time.
Intent Streams
Creates streams out of user interactions with our player's components.
Combines these with streams from playerFacade to generate streams that represent a request to do something with our player.
- Play.
- Open Share Tools.
- Load Video.
- ...
Other Inputs
playerEvent$ creates streams out of DOM events coming from our player (these could be either from a video or ad).
configStreams creates single-event streams that come either from the initial player response (playerConfig$, environment$) or miscellaneous set-up (e.g. user agent checking).
windowEvents creates streams off of, well, events happening on the window.
Model
Contains the bulk of our business logic.
Leverages Rx to turn the various input streams into.
Streams that make sense for our player and analytics.
View
Where the subscriptions happen.
The view has access to the player and its components, and performs updates
We try to err away from having logic in the view, though there are many exceptions to this at the moment
Sinks
Where the numbers happen.
Entry point for analytics and custom emitted events that do not directly affect our player.
Like the view, each of these sinks calls .subscribe() on some Observable to recieve custom events.
Each sink currently provides its own logic to transform its input streams, though ideally we would combine this all into one.
VideoJS
Where the magic happen?
Open source video player with support for
plugins & add-ons.
Provides a way to create
custom techs & source handlers.
VideoJS Plugins
We don't use them.
VideoJS add-ons
Only one currently in use is videojs-contrib-hls.
(that may change with DFP)
Our hls add-on usage is pretty basic, but it does provide an API for customizing the video quality if need be.
We this gives us an HLS source-handler for free, which means we don't need to write our own techs
VideoJS Techs
That said, we wrote our own techs (thanks to ads) :)
Keeping this high level this because we'll be throwing it all out for DFP (sorry Scott) :(
For flash sources(.swf) we wrote a tech from the ground up,
for javascript sources, we extended the existing html5 tech with a custom source handler.
VideoJS components
We mainly use custom components.
(see children.js)
They provide handlers for various user interactions,
which we turn into IntentStreams,
and,
we've gone full circle...
Ad
vertisements
IMPACT - Dust Jacket
Thumbnail & title optimizations have been shown to
increase CTR up to 200%.
1 Ring,
1 Fellowship
8 Fellowes
Copy of Player Spring '17
By Eric Wexler
Copy of Player Spring '17
- 733