TN9002: Episode Core: Episode Level Content Management
Abstract
Act Player and Episode Core are the core component to manage multiple contents that creator made. In this article, we will introduce the anatomy of these parts and give a brief guide about how customizing your player for both visual experience and functions which can fit your very own requirement.
Episode Core
Episode Core is the fundamental part which can manage all content segments provided by creators, it will manage the following tasks:
Lifecycle Management: To ensure contents loads smoothly and does not crash due to memory spikes, we need a well-established lifecycle mechanism to schedule the preloading, loading and destroy task of each part of your content, we will how lifecycle works later.
Time synchronize and schedule: Synchronizing multiple media source like video channel and audio channel. triggering events for various purpose like displaying subtitles, showing additional tips at specific time point of the video, switching BGM at different time, etc.
Audio playback management: To make sure Autoplay related functions can work correctly, we built a time system which can manage all tasks related to audio playback with the Web Audio API. This can help us play any audio files after users triggered their first interaction with the page on any browser.
For video files, we split the file into two different parts: a video file and an audio files. There is an extension can handle this task in Recative Studio, after the file is imported, channel splitting, compatibility fixing and many other tasks can be finished automatically.
Resource management: Core Manager will manage all files imported to Recative Studio (like audio, video, subtitle files or texture files). It will preload necessary resources, automatically select different resource for different language and platform, select resource from multiple CDN and storage source (which make offline storage possible).
Task queue: Since JavaScript is a single-threaded language, we must design a scheduling mechanism to ensure that a large number of background tasks will not affect the rendering performance. Core Manager provides priority queues: the fast queue and the slow queue. You can arrange tasks into different queues according to the priority of the tasks. Core Manager will arrange the tasks without affecting rendering performance.
Content and ContentInstance
Content is the specification (or definition, configuration) of an
asset, and ContentInstance is
the class did the actual content management related work, like resources, and
lifecycle:
Timeline: which manage the time of different tracks when the timing of different tracks is out of sync, theTimelinecoordinates the different tracks according to priority configuration.AudioTrack: Plays the audio track of a video.AudioHost: Plays sound effects of the assets.SubsequenceManager: Allows the asset to create and control subsequences.managedCoreStateList: Manages subtitles and other states of the content.
The ContentInstance also keeps references to some global resources, like the
TaskQueue, which schedules async tasks.
Lifecycle
The ContentInstance has five different states:
idle: TheContentInstanceis created, but the user interface is not loaded yet.preloading: TheContentInstanceis created but the required resources are still loading.ready: TheContentInstanceis ready to be shown on the stage.destroying: TheContentInstanceis destroying itself.destroyed: TheContentInstanceis destroyed, all the resources it used to be released.
ContentInstance also can be manually set to shown or hidden. However,
the loading indicator but not the ContentInstance should not be shown to the
user when its state is not ready.
Sequence and Subsequence
The Sequence(segments, assets) is a series of Content. It controls the creation,
destruction, showing and hiding of each asset, switching between different
assets, time calculation and Synchronization.
Time calculation
Each asset in the Sequence has a duration. The value could be infinite if necessary (like interact point).
To calculate current time of the sequence, we add up all the finite duration of
played asset, and add the time from the Timeline of the current segment if
the duration is finite.
To seek a specific time in the sequence, we find the segment that the time falls in, and calculate the time in that asset.
Switching between assets
To start the internal process of asset switching, we:
- set the
nextSegmentto the order of the next asset. - set the
nextSegmentStartTimeto the start time of next Content after switching. - then call the internal
switchToNextContentmethod.
The switchToNextContent method will get the blocker of this asset switching.
and wait for the blocker to unblock new asset setup.
When there are nothing blocking the loading process, it will destroy the old
asset if the old asset has the earlyDestroyOnSwitch property, and create
the new asset.
After new asset created, we will wait for:
- The ready state of the new asset.
- The blocker to unblock final Switching.
- Dependencies of the asset to complete.
Then, we will show the new asset, destroy the old asset if it's not destroyed, then set the time and playing state on the new asset.
If the next asset does not have a preloadDisabled property, it will be
preloaded now.
It is possible to switch from or switch to undefined content. When the
sequence switches to undefined content, it will fire an end event.
Subsequence
Assets can create their own subsequences. subsequences are like the main
sequence, but some behaviors are managed by the parent sequence:
- The subsequence will be hidden if its parent content is hidden.
- The subsequence will not play if its parent content is not playing.
- The subsequence should also be destroyed when its parent content is destroyed.