You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
onAdStarted() is not called between consecutive interstitial breaks #3013
If interstitial breaks are consecutive, HlsInterstitialsAdsLoader.Listener.onAdStarted() is not called at the beginning of the second and third breaks.
The callback isn't called because the ads are not properly played. We look into a fix for this. Once the ads are played as intended by the setup of this playlist the callbacks are called accordingly.
For other readers, what is currently working, is putting all ads into a single ad group. This can be achieved by giving the same start position to all interstitials that should play consecutively without any primary content in between. This way ExoPlayer puts them into the same ad group and plays them as a group.
The approach above that was reported as not working is valid as well, but it's broken atm. We look into a fix for that. In the meanwhile you can stick to the same-start-position approach to achieve a similar behavior.
Hi @marcbaechinger , thanks for acknowledging and working on this issue. I just wanted to check if there’s any update or timeline for a fix. Really appreciate your efforts!
From the stream it looks to me that we have the configuration of two consecutive ad groups. The first ad group contains two ads with 20 and 40 seconds duration. The following ad group has a single ad with 60sec duration. Then there is 200sec of content before the next ad follows in the same structure as described above. The target duration of the stream is 4 secs.
With this stream playback of the ads work as expected. As far as I can see playback of the ads works, but I also see that the onAdStarted() event is not emitted.
Can you confirm that playback works for you and you are only missing the callback being invoked? That's the behavior I see with your stream.
If we agree on the state of above, then I think I have located the problem. It is related with a timeline update that then advances the live window for a given duration (about the 4 seconds of the target duration of a segment). This causes a sudden change of the playing period which is reported as a discontinuity of type SKIP. This then isn't correctly recognized by the HlsInterstitialsAdLoader as an ad start and hence the callback isn't correctly called.
I see several approaches to fix this and I'm currently figuring out what's the best way to do this. Please bare with me if it takes me some more time to look into this. Based on this I'm confident this will be fixed in the next release. In the meanwhile I'm thankful for your patience and the availability of the test stream so we can make this work.
Thanks for looking at this again.
I can confirm that playback was fine. The onAdStarted() callbacks were missing for the second and third ads.
Regarding the ad grouping, my understanding is that each ad belongs to its own ad group, rather than the configuration you observed, where the 20 and 40-second ads were grouped together and the 60-second ad formed a second group?
Thanks for confirming that playback works as expected.
Regarding the grouping I think the problem is the current implementation of how X-SNAP="in" is implemented in ExoPlayer.
The spec says:
If the list contains IN then the client SHOULD locate the segment
boundary closest to the scheduled resumption point from the
interstitial in the Media Playlist of the primary content and
resume playback of primary content at that boundary. If more than
one Media Playlist is contributing to playback, the client SHOULD
transition at the latest segment boundary.
I think my implementation of interpreting this part of is a bit naive (or lets say, it's just wrong). Currently the start position of the interstitial is determined by the start time of the segment closest to the resumption position from which the resume offset it subtracted. In the case of the configuration in your playlist for a live stream, this can not really work because at the moment the start position is calculated, the segment where the ad resumes to the content is not yet in the playlist (for live it's likely to be a point in time in the future). So currently it takes the end of the playlist and subtracts from there. Because this happens about 20 seconds after the previous ad with a duration of 20s, this snaps exactly to the same starting point as the previous ad. So they are grouped together.
I think instead the logic for X-SNAP:in must keep the defined start position and adjust the resume offset of the ad instead to match to the start of given resumption segment. For a live stream, this also needs to be deferred to the moment when that segment actually is added to the playlist. It can't be done at the point in time when the interstitial is inserted.
I'll follow up on this here in the thread when I have some changes pushed to the main branch.
The two commits above should fix the problem. Thanks for your report! Very useful!
I'm closing in the expectation that's fixed. Please open a new issue if you think something isn't right.
Activity
marcbaechinger commentedon Jan 19, 2026
Thanks for your report.
The callback isn't called because the ads are not properly played. We look into a fix for this. Once the ads are played as intended by the setup of this playlist the callbacks are called accordingly.
For other readers, what is currently working, is putting all ads into a single ad group. This can be achieved by giving the same start position to all interstitials that should play consecutively without any primary content in between. This way ExoPlayer puts them into the same ad group and plays them as a group.
The approach above that was reported as not working is valid as well, but it's broken atm. We look into a fix for that. In the meanwhile you can stick to the same-start-position approach to achieve a similar behavior.
work-keith commentedon Feb 9, 2026
Hi @marcbaechinger , thanks for acknowledging and working on this issue. I just wanted to check if there’s any update or timeline for a fix. Really appreciate your efforts!
marcbaechinger commentedon Feb 12, 2026
I looked into this again.
From the stream it looks to me that we have the configuration of two consecutive ad groups. The first ad group contains two ads with 20 and 40 seconds duration. The following ad group has a single ad with 60sec duration. Then there is 200sec of content before the next ad follows in the same structure as described above. The target duration of the stream is 4 secs.
With this stream playback of the ads work as expected. As far as I can see playback of the ads works, but I also see that the
onAdStarted()event is not emitted.Can you confirm that playback works for you and you are only missing the callback being invoked? That's the behavior I see with your stream.
If we agree on the state of above, then I think I have located the problem. It is related with a timeline update that then advances the live window for a given duration (about the 4 seconds of the target duration of a segment). This causes a sudden change of the playing period which is reported as a discontinuity of type
SKIP. This then isn't correctly recognized by theHlsInterstitialsAdLoaderas an ad start and hence the callback isn't correctly called.I see several approaches to fix this and I'm currently figuring out what's the best way to do this. Please bare with me if it takes me some more time to look into this. Based on this I'm confident this will be fixed in the next release. In the meanwhile I'm thankful for your patience and the availability of the test stream so we can make this work.
work-keith commentedon Feb 12, 2026
Thanks for looking at this again.
I can confirm that playback was fine. The onAdStarted() callbacks were missing for the second and third ads.
Regarding the ad grouping, my understanding is that each ad belongs to its own ad group, rather than the configuration you observed, where the 20 and 40-second ads were grouped together and the 60-second ad formed a second group?
marcbaechinger commentedon Feb 13, 2026
Thanks for confirming that playback works as expected.
Regarding the grouping I think the problem is the current implementation of how
X-SNAP="in"is implemented in ExoPlayer.The spec says:
I think my implementation of interpreting this part of is a bit naive (or lets say, it's just wrong). Currently the start position of the interstitial is determined by the start time of the segment closest to the resumption position from which the resume offset it subtracted. In the case of the configuration in your playlist for a live stream, this can not really work because at the moment the start position is calculated, the segment where the ad resumes to the content is not yet in the playlist (for live it's likely to be a point in time in the future). So currently it takes the end of the playlist and subtracts from there. Because this happens about 20 seconds after the previous ad with a duration of 20s, this snaps exactly to the same starting point as the previous ad. So they are grouped together.
I think instead the logic for X-SNAP:in must keep the defined start position and adjust the resume offset of the ad instead to match to the start of given resumption segment. For a live stream, this also needs to be deferred to the moment when that segment actually is added to the playlist. It can't be done at the point in time when the interstitial is inserted.
I'll follow up on this here in the thread when I have some changes pushed to the main branch.
[1] https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-19#appendix-C
Fix X-SNAP implementation
Turn SKIP discontinuity into an AUTO transition for ads
marcbaechinger commentedon Feb 20, 2026
The two commits above should fix the problem. Thanks for your report! Very useful!
I'm closing in the expectation that's fixed. Please open a new issue if you think something isn't right.
Fix X-SNAP implementation
Turn SKIP discontinuity into an AUTO transition for ads