Adventures in online lectures

by levien on zo 10 maart 2013 // Posted in misc // under

A few weeks ago I started teaching a mathematics-course for first-year biology students, as part of a larger three-month Systems Biology course at the University of Utrecht. A couple of years ago the university started to record a number of its lectures, which were then made available online for students and the general public. I think that this is a very good thing in general. From an educational perspective, it allows the students to choose where and when they follow lectures, and it allows them to revisit subjects that they may find difficult. From an open-access perspective, the university is paid for by public money, so it is good that its lectures are available online for the public. And not unimportantly, being able to watch your own lectures is also very useful for lecturers, as it allows you to improve on your presentation technique.

For recording an publishing their lectures, the University of Utrecht, like many universities, uses a commercial webcasting platform called Mediasite, by the US company Sonic Foundry. As could be expected, accessing the online lectures works fine on your average Windows computer. However, if you try to access a lecture using Firefox on a non-Windows system, or on Windows without Microsoft Silverlight installed, you just get a message telling you to install Silverlight. Being a Linux-user myself, I was quite annoyed that I apparently could not view my own lectures, because there is no Silverlight plugin for Linux. Microsoft does helpfully suggest that you could try the Novell Moonlight add-on for Firefox. While it is cool that Moonlight exists, I find it a bit ridiculous that you need to install a 30+ Mb plugin just to play videos. My (limited) experience with this add-in is that it's a memory hog, and older versions tended to crash the browser every now and then. More importantly, it does not provide a complete implementation of Silverlight (so it simply won't work with many sites), and it does not work with any recent Firefox version.

Being annoyed, of course I immediately started work at figuring out how to extract the video and audio streams from a Silverlight-based site, so I could at least watch the videos. This proved less than trivial, as the SmoothStreaming technique employed by Silverlight splits audio and video, and then breaks up both streams into small fragments. In theory this has the advantage that a server can offer video at multiple bitrates, and the player can dynamically choose fragments of an appropriate bitrate depending on the bandwidth and load of its network connection. In practice of course, many servers offer only a single bitrate, and the protocol just ends up being an overly complicated propitiatory way to serve video content, which only works well on Windows systems. Moreover, while I was able to find a way to download all audio- and video-fragments from the server (see below), getting them synchronised was not easy and required manual adjustment.

Obviously, these days online content is no longer accessed mostly on Windows computers using Internet Explorer or Firefox. Large numbers of people view webpages on a Mac or a non-Windows tablet, or using Google Chrome. This is why reliance on Adobe Flash or Microsoft Silverlight for video streaming is a bad idea, and will eventually disappear: A growing group of internet-users can no longer access content that requires such proprietary plug-ins. Presumably Sonic Foundry realised this, as it turns out their Mediasite platform complains that it needs Silverlight on Firefox, but works fine on Google Chrome and Safari without Silverlight! So it seems that Mediasite also provides an alternative HTML5 implementation that does not require plug-ins, and works using JavaScript and MPEG4 video streams. Unfortunately, the current version of Firefox (19) still lacks the required HTML5 support for playing H.264 video and AAC audio, which is why it asks for Silverlight. But at least the HTML5 implementation of Mediasite playback allows me to watch my own lectures at home using a different browser.

Unfortunately, the Linux-computers at the university only have Firefox installed. Moreover, Mediasite does not allow you to view both the slides and the video recording (which shows the blackboard) at a decent size, so unless you have a very large screen you cannot read both at the same time. Finally, Mediasite offers only limited sound-controls, and the sound-quality often isn't very good, making the online lectures hard to follow. This is a problem caused by bad recording, rather than by playback. If you watch this lecture, you will notice that the volume is quite low, and it drops even further every time I turn my head away from the microphone. This could have been prevented at the time of recording, by adjusting the position of the microphone, and perhaps by somewhat increasing the recording volume. Unfortunately there is no sound-check at the start of a lecture and I can't monitor the recording volume while talking, so I just notice these problems when the lecture is already online. Fortunately there is a technique called dynamic range compression, which is able to "stabilise" the overall volume level by increasing the volume of quiet parts and decreasing the volume of loud parts. But unfortunately there is no way to apply this to a video that is already hosted on Mediasite. That is, unless you download it, process the audio and then upload it somewhere else.

I figured out pretty quickly that you could download the video stream and the slide images from the Mediasite server. The video is offered by the server as an H.264 MPEG4-file, and the slides are simply JPEG-images. Their names and locations are specified in a file called manifest.js. So I wrote a little Perl-script that takes a Mediasite-URL as argument, grabs and parses the manifest-file, downloads the videos and slides, improves the audio quality and encodes everything into a single decent-quality video file, in which slides and video are shown side-by-side. I put the resulting videos in a YouTube playlist. Now anyone can view our lectures in decent quality on whichever browser they like, without having to rely on some company to sort out their interface. This, to me, is an important part of open access: Having publicly accessible content isn't much good if it's locked away in some proprietary platform, which dictates how and with which software you're allowed to view the content...

The script I wrote can be downloaded here. It has been designed for the LectureNet platform used by the University of Utrecht, which in turn is based on MediaSite. It will probably work for other Meadiasite-platforms, although it may require some adjustments. It currently requires the following external packages:

  • Perl, obviously, for running the script.
  • wget, for downloading files from the server.
  • FFMPEG >0.7 with x264-support, for decoding, combining and encoding the video streams.

  • MEncoder (which is part of the MPlayer package, for versions \<2.x), for concatenating the slides (in theory FFMPEG can do this, but so far I haven't been able to make that work properly).
  • SoX, for audio normalisation and dynamic range compression. An alternative would be to use vLevel.
  • Nero AAC encoder, for recompressing the audio after processing by SoX. An alternative would be to use FAAC or FFMPEG. Of course, recompression could also be done using another codec (e.g. MP3, using LAME).
  • ImageMagick, for combining the slide-images into a nice PDF-file.

This is what the script does:

  • Take the URL apart, and use it to download the manifest.js file
  • Parse the manifest, get presentation info, figure out the video and slide URLs and store the time-offset of each slide
  • Download all slide-JPEGs, calculate the duration of each slide, convert each JPEG into an H.264 video fragment
  • Concatenate all slide-video-fragments, and concatenate the JPEGs into a PDF-file
  • Download the video-recording of the presentation, split it into separate audio and video streams
  • Perform dynamic range compression and normalisation to improve the sound quality of the audio stream (this reduces fluctuations in the volume)
  • Compress the processed audio into an AAC stream
  • Combine the slide-video, the video recording and the new audio stream into a single H.264 file (actually two files with different output sizes)

The output will be stored in a new directory. There are some settings you may want to tweak or steps you may want to skip, check out the script itself for more information.


Update November 2020

Since I wrote the article 7 years ago, it seems that Mediasite changed the way it works quite a bit. Two years ago I wrote a new Python-script for someone, which takes a JSON-file from Mediasite and produces a shell-script to download the video and slides, and another shell script to generate a video file from the slides.

The python script takes as argument a JSON-file from Mediasite. I'm not exactly sure how this JSON-file is obtained, as someone sent it to me. The script generates a UNIX shell-script for downloading the presentation video and the slides (get_videos.sh) and another shell-script (convert_videos.sh) which will create a video file (videos/slides.mp4) from the slides.

The shell-scripts have a few dependencies. The convert_videos.sh script requires ffmpeg to convert the videos and sox to process the audio. The get_videos.sh script uses wget to download the slides and video files, although similar programs should also work (cURL, aria2, xidel, etc.). To access the Mediasite-files it also needs the relevant login-cookies in a cookies file (cookies.txt). You can export the cookies from your browser after logging into Mediasite, for instance in Chrome with the cookietxt-export plugin.

I haven't really tested these scripts as I didn't have access to a Mediasite data source, so I'm curious if it works (and how the JSON-file is obtained). Moreover, the scripts were written for Linux, although they should also work on MacOSX and in Windows if you install bash, ffmpeg, wget and sox.

To execute the scripts, just do something like this:

python3 process-mediasite-json.py output6.json
sh get_videos.sh
sh convert_videos.sh

For get_videos.sh, you'd need a valid cookies.txt with the Mediasite login cookies.