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

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