Automated Chapter Links in BBC Sounds and iPlayer with mosromgr

How we built a prototype chapter link service for BBC Sounds and iPlayer


How might we demonstrate working chapter points for TV and radio programmes, and offer up chapter data for programme teams to make use of in BBC Sounds and iPlayer?

In 2021, we open-sourced mosromgr, a Python library for extracting rich metadata from the running orders created for TV and radio programmes. Recently, mosromgr was greenlit for transfer to a 24/7 engineering operations team to process MOS messages and make the final machine readable running orders available to anyone in the BBC.

During this project cycle we also released a new version of mosromgr: v0.10.0, which made various improvements to the codebase and addressed several potential bugs by increasing test coverage. It's still in beta as we gather more feedback from other organisations.


Building on previous work such as Slicer and Live Segment Notifications, we wanted to complete a project cycle using the data extracted by this new pipeline. We held an ideation session for potential stakeholders from BBC Sounds, iPlayer, News Product and the World Service in order to discover needs and collect ideas from around the BBC.

The basis of the ideation was to showcase the kind of data coming out of mosromgr, and ask what everybody thought they could do with the data. We showed them we had:

  • Start/end timings of each section
  • Reference to media items used
  • The planned script
  • Timing of all pieces of content
  • Text labels e.g. for guests and interviewees

All of this data exists within OpenMedia, the tool our programme teams use to plan and manage the structure of their programmes for TV, radio and podcasts.


One of the ideas came from Jonny McGuigan, Senior News Editor in iPlayer. Jonny wanted:

  • The ability to view chapter markers (and upcoming contents) when viewing an episode
  • The ability to link to a chapter point within the context of a whole episode
  • Social media link cards for chapter URLs that would work well on platforms such as Twitter and Facebook

This idea felt like something we could build, so we decided to take it forward for a project cycle. Our cycles are eight weeks, with development book-ended by a week of research at the start and a wrap-up week at the end.

Project planning

In order to be able to deliver a prototype covering Jonny's requirements, we worked out that we needed to build four components:

  • Automated publication of a chapters playlist

    • The BBC publishes a "playlist" JSON file which can contain details such as the music tracks played. This can include chapter points. We intended to publish an augmented version of this playlist with our own editorial chapters.
  • BBC Media Player plugin

    • We needed to create a plugin which would load our enhanced playlist and show chapters on the player page in Sounds and iPlayer.
  • Twitter card generator

    • We needed to be able to create unique URLs for each chapter, and for the links to render a Twitter card unique to each chapter.
  • Chapter link forwarding service

    • We needed the chapter URLs to load Twitter cards but also redirect the user to the live BBC page for the episode player (which would then be enhanced by the player plugin).

We agreed this with Jonny, and proceeded to create tickets on a GitHub project board for the necessary work.

How we built it

In preparation for the start of the project, we designed a state machine for doing the basic processing of the final running order document. State machines are a part of a workflow service within AWS Step Functions. With a state machine we're able to create a series of Lambda functions, each of which performing a task as part of a workflow. Lambda functions can be implemented in Python, TypeScript, Golang or various other languages. In this project we used Python.

Initially, the state machine workflow correlated running orders with their respective BBC IDs (the brand ID and episode ID from the BBC programme information system known as PIPs); inserted records into a database; and published a web page for the relevant episode. Throughout the project cycle, we added functions to the state machine as needed.

AWS state machine

Automated publication of a chapters playlist

We simply downloaded the existing published playlist JSON file, and replaced the empty markers field with a list of chapters, including their start/end times, and the title and a description. We then published this augmented playlist file to our own public S3 bucket so that it could be accessed by the media player plugin.

BBC Media Player plugin

The BBC Media Player (known as SMP — standard media player) which powers BBC Sounds and iPlayer, has a JavaScript API and a range of advanced features including the ability to surface chapter markers on the timeline.

Building on some prior work on an earlier prototype, we constructed a new plugin which used the enhanced playlist file as a source of data for displaying a list of contents and decorating the player timeline with the chapters.

The table of contents includes a unique URL for each chapter, so that we can demonstrate sharing a link specifically to a particular chapter point within the episode.

BBC media player plugin

Twitter card generator

When pasting a chapter URL into Twitter, we wanted a Twitter card to be loaded, showing a relevant image and summary specific to the chapter shared.

We created a Lambda function which generated the necessary HTML for the card. We also ensured the relevant tags were included so that the same principle would apply to other sites and services like Facebook and Slack.

The HTML was generated by a Lambda at the end of the state machine, and saved into another public S3 bucket, essentially being used as a server of (very simple) static HTML files.

We also used the Python Imaging Library in the Lambda to overlay the chapter title on the episode's image, so that each chapter had its own unique image - not perfect but a good way to prove the concept. In future we could look into ways of extracting a suitable video frame from TV, or a relevant picture for radio — or even provide a way for programme teams to provide their own image for each chapter.

Twitter card example

Chapter link forwarding service

Obviously, this is just a prototype — and we don't have time or permission to alter the public facing Sounds and iPlayer pages for our own purposes.

In order to be able to generate a URL for each chapter which rendered a Twitter card and also redirected to the live BBC Sounds or iPlayer player page, we needed a service to dynamically redirect requests.

We had the idea to use a Lambda Function URL, a fairly new addition to AWS Lambda functionality. We used FastAPI and very quickly had a working proof-of-concept demonstrating that we could redirect requests coming from Twitter to the appropriate Twitter card HTML, and redirect all other requests (like clickthroughs from Tweets) to the relevant live Sounds or iPlayer page, with a hash pointing at the relevant chapter (which would then be loaded by the plugin).

Chapter link forwarding service

We modified it to work with the user agents of Twitter, Facebook and Slack, and developed a fully functional link forwarding service which renders Twitter cards and when people click the link in Twitter, sends them to the episode player page with the chapter loaded (if they have the plugin).

Here's a snippet of our FastAPI route for a BBC Sounds chapter link:

def sounds(episode_pid: str, segment_pid: str, chapter_slug: str, request: Request):
    ua = request.headers['user-agent']
    if is_crawler(ua):"User agent is a crawler, so redirecting to social card")
        card_url = f"{settings.cards_s3_url}/sounds/play/{episode_pid}/{segment_pid}/index.html"
        return RedirectResponse(card_url)"User agent is not a crawler, so redirecting to BBC Sounds")
    sounds_url = f"{BBC_URL}/sounds/play/{episode_pid}#{segment_pid}/{chapter_slug}"
    return RedirectResponse(sounds_url)


We succeeded in delivering the prototype. We proved it's possible to do this with a fully automated workflow without getting production teams to change the way they work. We presented the demo at our end-of-cycle show-and-tell, and it went down well with the audience of internal BBC colleagues from across the organisation. This group included journalists, senior editorial leaders and producers from News, and product development staff from BBC Sounds and iPlayer.

We have identified issues and areas for improvement. We have considered potential solutions to these problems but we want to get feedback from stakeholders before we proceed.

The main problem is the lack of accuracy in the timing of events. Currently, we only receive an estimated time from Open Media (the planned transmission duration of each story/chapter within an episode), and we are investigating ways to access the accurate timings.

Secondly, we feel that the chapter titles used in the running order are not suitable for audiences. These are currenly written by producers, for producers, rather than external "consumers" such as our audiences. In a prior project cycle we developed a tool called Slicer which allowed a human editing process to add better audience facing titles and descriptions during a trial for Radio 4's Today programme.

Human-edited chapters from the R4 Today trial:

Human-edited chapters from the R4 Today trial

We have an idea which would allow programme producers and editorial staff to provide an audience-facing version of the chapter title and description in OpenMedia, enabling access to better titles without introducing a new tool or an additional workflow step after broadcast.


  • We completed the prototype and demonstrated the concept
  • We want to work with product teams in Sounds and iPlayer to discuss taking the ideas forward into those products
  • We also want to work with programme teams to improve the chapter titles and add descriptions and bespoke images
  • We aim to discover a method of obtaining accurate story timings


Love data and code?

We'd like to hear from you.