beraliv

Subtitles, statistics and DRM in Udemy video player (2020 edition)

Udemy player page
Udemy player page

I’ve discovered Udemy as a service around 5–6 years ago. Below you can read what I found interesting having a look at the player during several hours.

WebVTT

The Web Video Text Tracks Format, or WebVTT, is a specification to mark up external text track resources and put them to <track> elements.

There is an implementation for Node.js and browsers which is called vtt.js (versions by VideoJS and Mozilla).

It turns out Udemy uses VideoJS version 0.12.4 (28 Apr 2017) as a fallback value. The version for me was 0.12.6 (13 Feb 2018).

VTT-files look like that:

VTT subtitles file structure
VTT subtitles file structure

Udemy also uses WebVTT to show a popover using thumbnail sprites:

VTT thumbnail sprites file structure
VTT thumbnail sprites file structure

Video.js Sneakpeek is used to parse VTT sprites. If you're interested in what videojs-sneakpeek.min.js looked like when Udemy used it in 2020, please check my gist (it has 14K lines of codes so it can take up to 10 seconds to load the gist).

Statistics

Video player development isn’t obvious: it includes browser-specific features (e.g. Fullscreen API, Promise, JavaScript modules via script tag, etc), depends on the other libraries which are used (e.g. hls.js, shaka-player, videojs and so on). This is why it’s a general approach to send player events and to analyse data later.

Udemy uses XMLHttpRequest in _sendBeaconQueue for synchronous and sendBeacon in _clearBeaconQueue for asynchronous requests. The data is sent as a sequence of events.

Statistics synchronous event example
1{
2 mapve: "2.0",
3 bdm: "litix.io",
4 psqno: 26,
5 xsqno: 26,
6 pispa: false,
7 pphti: 1339532,
8 uti: 1578401570429,
9 ake: "vfq2nsli1v76fglgdl9puq0cd",
10 vid: 247298,
11 xid: "50097cd1-9249-4b4c-a1cf-a6de924abadc",
12 xwati: 16971,
13 xrefq: 0.000058924046903541334,
14 xrepe: 0.020859112603853633,
15 sex: 1578403070430,
16 e: "play"
17}

The full XMLHttpRequest example is available here. You can see UTC timestamp as uti, event name as e, video id as vid, etc. The events are send to https://<ake>.litix.io where <ake> is user id. The beaconUrl is https://vfq2nsli1v76fglgdl9puq0cd.litix.io.

Statistics asynchronous event example
1{
2 mapve: "2.0",
3 memve: "2.7.0",
4 ualnm: "Chrome",
5 ualve: "79.0.3945.88",
6 ualeg: "Blink",
7 udvnm: null,
8 udvcg: "",
9 udvmn: null,
10 uosfm: "OS X",
11 uosar: 64,
12 uosve: "10.15.2",
13 pinid: "07auyu",
14 msara: 1,
15 bdm: "litix.io",
16 psqno: 8,
17 xsqno: 8,
18 pispa: false,
19 pisfs: false,
20 pauon: true,
21 ppron: "auto",
22 pwd: 760,
23 pht: 494,
24 placd: "en-us",
25 vsomity: "video/mp4",
26 vsodu: 1203002,
27 vsoht: 720,
28 vsowd: 1280,
29 pphti: 6648,
30 uti: 1578423421619,
31 pswnm: "Video.js",
32 pswve: "6.12.1",
33 pmxpinm: "videojs-mux",
34 pmxpive: "2.5.0",
35 ake: "vfq2nsli1v76fglgdl9puq0cd",
36 pnm: "Lecture Video Player",
37 piiti: 1578423407410,
38 uusid: "x01hQuPoFKZNyZJ-CFzjb7bWQ==",
39 vid: 258661,
40 vdn: "centurylink",
41 vtt: 258661,
42 vdu: 1203,
43 vsmty: "on-demand",
44 vsr: 41295,
45 fnm: 0,
46 xid: "d5430c5b-eccb-494f-a5b3-260a21bc869d",
47 xwati: 6766,
48 xskco: 1,
49 xskdu: 119,
50 xmaskti: 119,
51 pvwco: 1,
52 xst: 1578423414954,
53 xtitofifr: 130,
54 xagsuti: 26144278,
55 xctpbti: 6634,
56 vsoisli: false,
57 vsodm: "udemycdn.com",
58 vsohn: "a2.udemycdn.com",
59 sid: "efdff00e-15a0-4fc0-9cb5-c36da18fdaa4",
60 sst: "1578423398399",
61 sex: 1578424921620,
62 mvrid: "5f28be71-d37d-4a5d-bc4c-c1e1cdef474c",
63 msano: "0.21694370671278884",
64 e: "viewend",
65 wur: "https://www.udemy.com/course/learn-html5-programming-from-scratch/learn/lecture/235793#overview",
66 vpour: "",
67 vsour: "https://a2.udemycdn.com/2013-03-01_00-27-17-15d79c069f7f94ff9b8037f0ab0bad3f/WebHD_720p.mp4?<...private-params-for-access>"
68}

The full sendBeacon example is available here. You can see more data about browser, OS, libraries, content, course and so on and so forth. The beaconUrl here is https://vfq2nsli1v76fglgdl9puq0cd.litix.io as well.

DRM

All my old courses’ videos (and even the one I purchased now) are MP4. I didn’t find anything that includes DRM. However, the url to the stream includes 2 GET-parameters to have access to it: nva and token, otherwise access is forbidden.

Video tag element contains the source to the stream and plays it just fine. If you try to put src without those parameters, you will get the error:

Udemy player MEDIA_ERR_SRC_NOT_SUPPORTED error
Udemy player MEDIA_ERR_SRC_NOT_SUPPORTED error
player

Comments

Alexey Berezin profile image

Written by Alexey Berezin who loves London 🏴󠁧󠁢󠁥󠁮󠁧󠁿, players ⏯ and TypeScript 🦺 Follow me on Twitter