Skip to main content

Timeline Events

The fl-stream-timeline library facilitates streaming real-time events for an on-going live stream to enable rich, interactive Live experiences.

Create StreamTimelineManager

Use the following configuration and manager settings to set up timeline events for your live stream.

StreamTimelineConfiguration

ValuesTypeDescription
leagueNameStringThe league name for the content to play. For example: NHL, NBA, IPL
gameIdStringThe identifier for the particular game
spoilerBooltrue to receive events as soon as available, false to receive events as per playhead progress. Default value is false

StreamTimelineManager

ValuesTypeDescription
configurationStreamTimelineConfigurationThe configuration information required by the manager
playerPlayerThe player that's playing the content. It should confirm to EventSendableDelegate to receive events

let streamTimelineConfig = FLStreamTimelineFactory.streamTimelineConfiguration(leagueName: "NHL", gameId: "2354717", spoiler: false)
let streamTimelineManager = FLStreamTimelineFactory.streamTimelineManager(configuration: streamTimelineConfig, player: player)
// Check if the game is available to subscribe
streamTimelineManager.canSubscribeEvents { isSuccess in
if isSuccess {
// Subscribe to timeline events
streamTimelineManager.subscribeEvents { result in
switch result {
case .success:
print("StreamTimeline subscribed!")
case .failure:
print("StreamTimeline subscribe failed!")
}
}
}
}
caution

Firebase charges for document reads and writes, so we recommend creating the TimelineManager lazily.

Listen to Player Events

The player should confirm to EventSendableDelegate to receive events. Once you've subscribed the StreamTimelineManager, you can receive real-time stream timeline events on the Player instance.

StreamTimelineEvent

ValueDescription
gameInfoThe Game metadata event received in the gameInfo type
gameEventThe StreamTimeline events are received in the gameEvent type

Action

ValueDescription
noneNo action is required on the playback. For example: playback start or playback end

StreamTimelineMetadata

ValuesTypeDescription
eventMetadata[String: Any]The metadata of the stream timeline event
typeChangeTypeThe stream timeline event type of action that happened on the event

ChangeType

ValueDescription
addedA new event added to the stream timeline
modifiedThe existing event metadata is modified
deletedThe existing event metadata is deleted
unknownThe event is triggered without type info. StreamTimelineEvent.gameInfo is received on this type
func didReceive(event: StreamTimelineEvent, suggestedAction: Action, metadata: StreamTimelineMetadata?) { 
switch event {
case .gameInfo:
guard let data = metadata as? TimelineEventMetadata else { return }
print("Game Info Metadata: \(data.eventMetadata)")
break
case .gameEvent:
guard let data = metadata as? TimelineEventMetadata else { return }
print("Game Event Metadata: \(data.eventMetadata)")
switch data.type {
case .added:
// put your logic here
case .modified:
// put your logic here
case .deleted:
// put your logic here
default:
break
}
break
default:
break
}
}

JSONSchema

The following JSON schemas define the structure of game information and game events.

Game Info

{
"id": {
"type": "string"
},
"matchNumber": {
"type": "string"
},
"season": {
"type": "string"
},
"series": {
"type": "string"
},
"scheduledStart": {
"type": "string",
"format": "date-time"
},
"timestamp": {
"type": "string",
"format": "date-time"
},
"venue_id": {
"type": "string"
},
"venue_name": {
"type": "string"
},
"game_year": {
"type": "string"
},
"teams": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"code": {
"type": "string"
},
"id": {
"type": "string"
},
"images": {
"type": "array",
"items": [
{
"type": "string"
}
]
},
"region": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"home",
"visitor"
]
},
"players": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"currentTeam": {
"type": "string"
},
"name": {
"type": "string"
},
"images": {
"type": "array",
"items": [
{
"type": "string"
}
]
},
"id": {
"type": "string"
},
"number": {
"type": "string"
},
"position": {
"type": "string"
}
}
}
]
}
}
}
]
}
}

Game Event

{
"description": {
"type": "string"
},
"id": {
"type": "string",
"format": "date-time"
},
"teamInvolved": {
"type": "string",
"enum": [
"home",
"visitor"
]
},
"timestamp": {
"type": "string",
"format": "date-time"
},
"period": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"period_start",
"period_end",
"overtime_start",
"overtime_end",
"shootout_start",
"shootout_end",
"break_start",
"break_end",
"goal",
"penalty",
"penalty_shot"
]
},
"startTime": {
"type": "string",
"format": "date-time"
},
"players": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"winner",
"loser",
"shooter",
"goalie",
"scorer",
"assist",
"unknown",
"blocker",
"hitter",
"hittee"
]
}
}
}
]
},
"scorecard": {
"type": "object",
"properties": {
"total": {
"type": "object",
"properties": {
"visitor": {
"type": "string"
},
"home": {
"type": "string"
}
}
},
"goals_by_period": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"visitor": {
"type": "string"
},
"home": {
"type": "string"
},
"period": {
"type": "string"
}
}
}
]
}
}
}
}

Stop listening to StreamTimeline events

Call this method when closing the player or when you're no longer interested in listening to stream timeline events.


streamTimelineManager.shutdown()