Search code examples
androidaudio-streamingexoplayer

ExoPlayer, how to load bigger parts of remote audio files


I'm using ExoPlayer 2 to play remote tracks. By default the player loads tracks piece by piece (i.e. about 20 seconds, then other 20 seconds while the track is playing).

Since tracks are loaded from a remote server, it happens that if connection goes down, the player is not able to load anymore. Is there a way to say to ExoPlayer to load bigger parts of the audio file (also the full track at once)?

I tried to see around ExtractorMediaSource, DataSource.Factory and DefaultExtractorsFactory but I've found nothing to solve my problem.

val audioSource = ExtractorMediaSource(
        Uri.parse(videoUrl),
        mDataSourceFactory,    // DataSource.Factory
        mExtractor,    // DefaultExtractorsFactory
        null,
        null
)

mExoPlayer.prepare(audioSource)
mExoPlayer.playWhenReady = true

(it is Kotlin, but it seems to be understandable also by Java programmers)


Solution

  • I've found the solution. Since I'm not finding other related questions, I'll answer to my question (I hope someone will need it in the future):

    The right object to configure is the LoadControl passed to the ExoPlayerFactory when creating the ExoPlayer object:

    Original answer (deprecated):

    val loadControl = DefaultLoadControl(
                DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
                5 * 60 * 1000, // this is it!
                10 * 60 * 1000,
                DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS.toLong(),
                DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS.toLong()
    )
    exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl)
    

    The updated answer:

    val bandwidthMeter = DefaultBandwidthMeter.Builder(context).build()
    val trackSelectionFactory = AdaptiveTrackSelection.Factory()
    val trackSelector = DefaultTrackSelector(trackSelectionFactory)
    
    val loadControl = DefaultLoadControl.Builder()
            .setAllocator(DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE))
            .setBufferDurationsMs(
                5 * 60 * 1000, // this is it!
                10 * 60 * 1000,
                DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
                DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS
            )
            .setTargetBufferBytes(DefaultLoadControl.DEFAULT_TARGET_BUFFER_BYTES)
            .setPrioritizeTimeOverSizeThresholds(DefaultLoadControl.DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS)
            .createDefaultLoadControl()
    
    exoPlayer = ExoPlayerFactory.newSimpleInstance(
            context,
            DefaultRenderersFactory(context),
            trackSelector,
            loadControl,
            null,
            bandwidthMeter)
    

    The doc where it is explained.