Reputation: 11
I am playing an HLS stream (m3u8 playlist) in my compose app. The stream is coming from a sensor and is made up of MPEG-TS segments (Video Only, no audio). The issue is when the stream comes, the first few segments are not found, you can see the logs of the sensor (test.ts 404), only subsequent streams are found:
The Android behavior seems to be retrying again and again, resulting in my stream showing up only after a huge delay of 30 seconds. Sensor's Android case logs
The IOS behavior is to simply skip the missing segment, and move on to retrieve the next segment and repeat, as shown in the logs : Sensor's IOS case logs
Here is an example mediaInfo of .ts segment :
General
ID : 1 (0x1)
Complete name : test_19.ts
Format : MPEG-TS
File size : 51.2 KiB
Duration : 5 s 205 ms
Overall bit rate mode : Variable
Overall bit rate : 80.6 kb/s
Frame rate : 30.000 FPS
Video
ID : 65 (0x41)
Menu ID : 1 (0x1)
Format : AVC
Format/Info : Advanced Video Codec
Format profile : Baseline@L1
Format settings : 1 Ref Frames
Format settings, CABAC : No
Format settings, Reference frames : 1 frame
Format settings, GOP : M=1, N=30
Codec ID : 27
Duration : 5 s 49 ms
Bit rate : 76.6 kb/s
Width : 640 pixels
Height : 360 pixels
Display aspect ratio : 16:9
Frame rate : 30.000 FPS
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Bits/(Pixel*Frame) : 0.011
Stream size : 47.1 KiB (92%)
and here is example of Hls playlist manifest :
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:NO
#EXT-X-MEDIA-SEQUENCE:19
#EXT-X-TARGETDURATION:5
#EXTINF:5.068028450012207,
test_17.ts
#EXTINF:5.0681610107421875,
test_05.ts
#EXTINF:5.067845344543457,
test_10.ts
#EXTINF:5.0680408477783203,
test_21.ts
#EXTINF:5.0680079460144043,
test_22.ts
I tried out multiple things, notably allowingChunklessPreparation/ LoadErrorHandlingPolicy/ autoSeeking / Passing different flags to mediaSource/ Playing the HLS with an implemented package that uses exoplayer internally etc, as can be seen from my code and comments (in code) :
fun LiveStreamPlayer(url: String) {
val context = LocalContext.current
val mediaUrl = (context as MainActivity).mainViewModel.livestreamUrl.value!!.data
Timber.e("media item livestreamurl: $mediaUrl")
val livestreamLogs = remember { mutableStateListOf<String>() }
val exoPlayer = remember { ExoPlayer.Builder(context).build()}
LaunchedEffect(key1 = Unit) {
val dataSourceFactory = DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true)
val mediaSource = HlsMediaSource
.Factory(dataSourceFactory)
.createMediaSource(
MediaItem.fromUri(mediaUrl)
)
exoPlayer.apply {
addListener(object : Player.Listener {
override fun onPlayerError(error: PlaybackException) {
Timber.e("ExoPlayer error: ${error.message}")
livestreamLogs.add("error ${error.errorCode}: ${error.errorCodeName}")
// Handle error
}
override fun onPlaybackStateChanged(playbackState: Int) {
Timber.e("Playback state changed: $playbackState")
livestreamLogs.add("playback state change : ${playbackState}")
}
}
)
setMediaSource(mediaSource)
prepare()
playWhenReady = true
}
}
DisposableEffect(
Column(
modifier = Modifier
.fillMaxSize()
) {
AndroidView(
modifier = Modifier
.height(300.dp)
.fillMaxWidth(),
factory = {
val playerView = PlayerView(context)
playerView.apply {
player = exoPlayer
//useController = false
}
playerView
}
)
Spacer(modifier = Modifier.height(10.dp))
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(horizontal = 16.dp)
.padding(bottom = 80.dp),
) {
items(livestreamLogs.size) { log ->
Text(livestreamLogs[log])
}
}
}
) {
onDispose {
Timber.e("exoplayer disposed")
exoPlayer.release()
}
}
}
In summary how can i force Exoplayer to skip a segment if not found and move on instantly to next segment? (unfortunately i cannot provide the stream URL as it is provided dynamically on command to the sensor)
Any help is appreciated, and if further info are needed or my question is not clear, please do let me know.
Upvotes: 1
Views: 170
Reputation: 76779
When it replies with test..ts 404
, this means: file not found. The double-colon is suspicious ..
While that #EXTM3U
does not even have test..ts
(that's a whole other). Just fix the playlist.
One could as well check, if any of the segments is 404
before enqueuing them.
But fixing the playlist which the "sensor" sends appeary to be the most reliable.
MediaSource
uses Timeline
internally: Live stream with multiple periods.
Or to obtain the filenames to check for 404
: Accessing the manifest.
Upvotes: 0