ExoPlayer kitaplığının merkezinde Player
arayüzü bulunur. Player
, medyayı arabelleğe alma, oynatma, duraklatma ve ileri sarma gibi geleneksel üst düzey medya oynatıcı işlevlerini gösterir. Varsayılan uygulama ExoPlayer
; oynatılan medyanın türü, nasıl, nerede depolandığı ve nasıl oluşturulduğu hakkında birkaç varsayımda bulunmak (ve dolayısıyla birkaç kısıtlama getirmek) için tasarlanmıştır. ExoPlayer
uygulamaları, medyanın yüklenmesini ve oluşturulmasını doğrudan uygulamak yerine bu işi, bir oynatıcı oluşturulduğunda veya oynatıcıya yeni medya kaynakları aktarıldığında enjekte edilen bileşenlere devreder.
Tüm ExoPlayer
uygulamalarında ortak olan bileşenler şunlardır:
- Oynatılabilecek medyayı tanımlayan, medyayı yükleyen ve yüklenen medyanın okunabildiği
MediaSource
örnekleri.MediaSource
örneği, oynatıcıdaki birMediaSource.Factory
tarafındanMediaItem
öğesinden oluşturulur. Ayrıca, medya kaynağına dayalı oynatma listesi API'si kullanılarak doğrudan oynatıcıya aktarılabilirler. - Bir
MediaItem
değeriniMediaSource
değerine dönüştüren birMediaSource.Factory
örneği.MediaSource.Factory
, oynatıcı oluşturulduğunda eklenir. - Medyanın bağımsız bileşenlerini oluşturan
Renderer
örnek. Bunlar, oynatıcı oluşturulduğunda eklenir. - Mevcut her bir
Renderer
tarafından kullanılacak,MediaSource
tarafından sağlanan parçaları seçen birTrackSelector
. Oynatıcı oluşturulduğunda birTrackSelector
eklenir. MediaSource
'un ne zaman daha fazla medyayı arabelleğe aldığını ve ne kadar medyanın arabelleğe alındığını kontrol eden birLoadControl
. Oynatıcı oluşturulduğundaLoadControl
yerleştirilir.- Oynatıcının yapılandırılmış bir canlı ofsete yakın kalmasını sağlamak için canlı oynatma sırasında oynatma hızını kontrol eden bir
LivePlaybackSpeedControl
. Oynatıcı oluşturulduğundaLivePlaybackSpeedControl
yerleştirilir.
Oyuncu işlevlerinin parçalarını uygulayan bileşenleri ekleme kavramı kitaplığın her yerinde mevcuttur. Bazı bileşenlerin varsayılan uygulamaları, işi daha fazla enjekte edilen bileşenlere devreder. Bu sayede birçok alt bileşen, özel bir şekilde yapılandırılan uygulamalarla tek tek değiştirilebilir.
Oyuncu özelleştirme
Bileşen ekleyerek oynatıcıyı özelleştirmeyle ilgili bazı yaygın örnekler aşağıda açıklanmıştır.
Ağ yığınını yapılandırma
ExoPlayer tarafından kullanılan ağ yığınını özelleştirme hakkında bir sayfamız var.
Ağdan yüklenen verileri önbelleğe alma
Geçici anında önbelleğe alma ve medya indirme ile ilgili kılavuzları inceleyin.
Sunucu etkileşimlerini özelleştirme
Bazı uygulamalar, HTTP isteklerine ve yanıtlarına müdahale etmek isteyebilir. Özel istek üstbilgileri eklemek, sunucunun yanıt üstbilgilerini okumak, isteklerin URI'lerini değiştirmek vb. isteyebilirsiniz. Örneğin, uygulamanız medya segmentlerini isterken üstbilgi olarak bir jeton ekleyerek kimliğini doğrulayabilir.
Aşağıdaki örnekte, DefaultMediaSourceFactory
içine özel bir DataSource.Factory
ekleyerek bu davranışların nasıl uygulanacağı gösterilmektedir:
Kotlin
val dataSourceFactory = DataSource.Factory { val dataSource = httpDataSourceFactory.createDataSource() // Set a custom authentication request header. dataSource.setRequestProperty("Header", "Value") dataSource } val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory) ) .build()
Java
DataSource.Factory dataSourceFactory = () -> { HttpDataSource dataSource = httpDataSourceFactory.createDataSource(); // Set a custom authentication request header. dataSource.setRequestProperty("Header", "Value"); return dataSource; }; ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)) .build();
Yukarıdaki kod snippet'inde, enjekte edilen HttpDataSource
her HTTP isteğinde "Header: Value"
üst bilgisini içerir. Bu davranış, bir HTTP kaynağıyla yapılan her etkileşim için sabittir.
Daha ayrıntılı bir yaklaşım için ResolvingDataSource
kullanarak tam zamanında davranış ekleyebilirsiniz. Aşağıdaki kod snippet'inde, istek üst bilgilerinin bir HTTP kaynağıyla etkileşime geçmeden hemen önce nasıl ekleneceği gösterilmektedir:
Kotlin
val dataSourceFactory: DataSource.Factory = ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec -> // Provide just-in-time request headers. dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri)) }
Java
DataSource.Factory dataSourceFactory = new ResolvingDataSource.Factory( httpDataSourceFactory, // Provide just-in-time request headers. dataSpec -> dataSpec.withRequestHeaders(getCustomHeaders(dataSpec.uri)));
Aşağıdaki snippet'te gösterildiği gibi, URI'de tam zamanında değişiklikler yapmak için ResolvingDataSource
kullanabilirsiniz:
Kotlin
val dataSourceFactory: DataSource.Factory = ResolvingDataSource.Factory(httpDataSourceFactory) { dataSpec: DataSpec -> // Provide just-in-time URI resolution logic. dataSpec.withUri(resolveUri(dataSpec.uri)) }
Java
DataSource.Factory dataSourceFactory = new ResolvingDataSource.Factory( httpDataSourceFactory, // Provide just-in-time URI resolution logic. dataSpec -> dataSpec.withUri(resolveUri(dataSpec.uri)));
Hata işleme ayarlarını özelleştirme
Özel bir LoadErrorHandlingPolicy
uygulamak, uygulamaların ExoPlayer'ın yükleme hatalarına tepki verme biçimini özelleştirmesine olanak tanır. Örneğin, bir uygulama çok kez tekrar denemek yerine hızlıca başarısız olmak isteyebilir veya oynatıcının her yeniden deneme arasında ne kadar bekleyeceğini kontrol eden geri yükleme mantığını özelleştirmek isteyebilir. Aşağıdaki snippet, özel geri çekme mantığının nasıl uygulanacağını gösterir:
Kotlin
val loadErrorHandlingPolicy: LoadErrorHandlingPolicy = object : DefaultLoadErrorHandlingPolicy() { override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorInfo): Long { // Implement custom back-off logic here. return 0 } } val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context).setLoadErrorHandlingPolicy(loadErrorHandlingPolicy) ) .build()
Java
LoadErrorHandlingPolicy loadErrorHandlingPolicy = new DefaultLoadErrorHandlingPolicy() { @Override public long getRetryDelayMsFor(LoadErrorInfo loadErrorInfo) { // Implement custom back-off logic here. return 0; } }; ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory( new DefaultMediaSourceFactory(context) .setLoadErrorHandlingPolicy(loadErrorHandlingPolicy)) .build();
LoadErrorInfo
bağımsız değişkeni, mantığı hata türüne veya başarısız isteğe göre özelleştirmek için başarısız yükleme hakkında daha fazla bilgi içerir.
Ayıklayıcı işaretlerini özelleştirme
Ayıklayıcı işaretleri, progresif medyadan tek tek biçimlerin ayıklanma şeklini özelleştirmek için kullanılabilir. Bunlar, DefaultMediaSourceFactory
sağlayıcısına sağlanan DefaultExtractorsFactory
üzerinde ayarlanabilir. Aşağıdaki örnekte, MP3 akışları için dizin tabanlı aramayı etkinleştiren bir işaret iletilmektedir.
Kotlin
val extractorsFactory = DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING) val player = ExoPlayer.Builder(context) .setMediaSourceFactory(DefaultMediaSourceFactory(context, extractorsFactory)) .build()
Java
DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory().setMp3ExtractorFlags(Mp3Extractor.FLAG_ENABLE_INDEX_SEEKING); ExoPlayer player = new ExoPlayer.Builder(context) .setMediaSourceFactory(new DefaultMediaSourceFactory(context, extractorsFactory)) .build();
Sabit bit hızı aramayı etkinleştirme
MP3, ADTS ve AMR akışları için FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
işaretleriyle sabit bit hızı varsayımı kullanarak yaklaşık aramayı etkinleştirebilirsiniz.
Bu işaretler, yukarıda açıklanan ayrı DefaultExtractorsFactory.setXyzExtractorFlags
yöntemleri kullanılarak ayrı ayrı ayıklayıcılar için ayarlanabilir. Destekleyen tüm ayıklayıcılarda sabit bit hızı arama özelliğini etkinleştirmek için DefaultExtractorsFactory.setConstantBitrateSeekingEnabled
işlevini kullanın.
Kotlin
val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)
Java
DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
Ardından ExtractorsFactory
, yukarıdaki ayrıştırıcı işaretlerini özelleştirme bölümünde açıklandığı gibi DefaultMediaSourceFactory
aracılığıyla enjekte edilebilir.
Eşzamansız arabellek sırasına almayı etkinleştirme
Zaman uyumsuz tampon sırası, ExoPlayer'ın oluşturma ardışık düzeninde yapılan bir iyileştirmedir. Bu iyileştirme, MediaCodec
örneklerini zaman uyumsuz modda çalıştırır ve verilerin kodunun çözülmesini ve oluşturulmasını planlamak için ek iş parçacıkları kullanır. Bu özelliği etkinleştirmek, atlanan kareleri ve ses eksikliklerini azaltabilir.
Asenkron arabellek sırası, Android 12 (API düzeyi 31) ve sonraki sürümleri çalıştıran cihazlarda varsayılan olarak etkindir ve Android 6.0 (API düzeyi 23) ile başlayarak manuel olarak etkinleştirilebilir. Özellikle DRM korumalı veya yüksek kare hızı içeren içerikleri oynatırken kare atlama veya ses eksikliği gözlemlediğiniz belirli cihazlarda bu özelliği etkinleştirebilirsiniz.
En basit durumda, oynatıcıya aşağıdaki gibi bir DefaultRenderersFactory
eklemeniz gerekir:
Kotlin
val renderersFactory = DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing() val exoPlayer = ExoPlayer.Builder(context, renderersFactory).build()
Java
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(context).forceEnableMediaCodecAsynchronousQueueing(); ExoPlayer exoPlayer = new ExoPlayer.Builder(context, renderersFactory).build();
Oluşturucuları doğrudan örneklendiriyorsanız MediaCodecVideoRenderer
ve MediaCodecAudioRenderer
yapıcılarına bir AsynchronousMediaCodecAdapter.Factory
aktarın.
ForwardingPlayer
ile yöntem çağrılarını durdurma
Bir Player
örneğinin davranışının bir kısmını, ForwardingPlayer
alt sınıfına sarmalayarak ve aşağıdakilerden herhangi birini yapmak için yöntemleri geçersiz kılarak özelleştirebilirsiniz:
- Parametrelere, temsilci
Player
'ye iletmeden önce erişin. - Döndürülen değeri,
Player
temsilcisinden döndürmeden önce erişin. - Yöntemi tamamen yeniden uygulayın.
ForwardingPlayer
yöntemlerini geçersiz kılarken, özellikle aynı veya ilgili davranışa sahip olması amaçlanan yöntemlerle çalışırken uygulamanın tutarlı ve Player
arayüzüne uygun kalmasını sağlamak önemlidir. Örnek:
- Her "play" işlemini geçersiz kılmak istiyorsanız hem
ForwardingPlayer.play
hem deForwardingPlayer.setPlayWhenReady
'ü geçersiz kılmanız gerekir. ÇünküplayWhenReady = true
olduğunda, çağıran bu yöntemlerin davranışının aynı olmasını bekler. - İleri sarma artışını değiştirmek istiyorsanız özelleştirilmiş artışınızla arama yapmak için
ForwardingPlayer.seekForward
'ü ve doğru özelleştirilmiş artışı arayana bildirmek içinForwardingPlayer.getSeekForwardIncrement
'ü geçersiz kılmanız gerekir. - Bir oynatıcı örneği tarafından hangi
Player.Commands
reklamlarının gösterileceğini kontrol etmek istiyorsanız hemPlayer.getAvailableCommands()
hem dePlayer.isCommandAvailable()
'yi geçersiz kılmanız ve temel oynatıcıdan gelen değişikliklerden haberdar olmak içinPlayer.Listener.onAvailableCommandsChanged()
geri çağırma işlevini de dinlemeniz gerekir.
MediaSource özelleştirme
Yukarıdaki örneklerde, oynatıcıya iletilen tüm MediaItem
nesnelerinin oynatılması sırasında kullanılmak üzere özelleştirilmiş bileşenler enjekte edilir. Ayrıntılı özelleştirmenin gerektiği durumlarda, özelleştirilmiş bileşenleri doğrudan oynatıcıya iletilebilecek tekil MediaSource
örneklerine yerleştirmek de mümkündür. Aşağıdaki örnekte, özel bir DataSource.Factory
, ExtractorsFactory
ve LoadErrorHandlingPolicy
kullanmak için bir ProgressiveMediaSource
öğesinin nasıl özelleştirileceği gösterilmektedir:
Kotlin
val mediaSource = ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory) .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy) .createMediaSource(MediaItem.fromUri(streamUri))
Java
ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(customDataSourceFactory, customExtractorsFactory) .setLoadErrorHandlingPolicy(customLoadErrorHandlingPolicy) .createMediaSource(MediaItem.fromUri(streamUri));
Özel bileşenler oluşturma
Kitaplık, yaygın kullanım alanları için bu sayfanın en üstünde listelenen bileşenlerin varsayılan uygulamalarını sağlar. ExoPlayer
bu bileşenleri kullanabilir ancak standart olmayan davranışlar gerekiyorsa özel uygulamalar kullanacak şekilde de derlenebilir. Özel uygulamalar için bazı kullanım alanları şunlardır:
Renderer
: Kitaplık tarafından sağlanan varsayılan uygulamalar tarafından desteklenmeyen bir medya türünü işlemek için özel birRenderer
uygulamak isteyebilirsiniz.TrackSelector
: Özel birTrackSelector
uygulamaya koymak, uygulama geliştiricilerin birMediaSource
tarafından sunulan parçaların mevcutRenderer
'lerin her biri tarafından tüketilmek üzere seçilme şeklini değiştirmelerine olanak tanır.LoadControl
: Özel birLoadControl
uygulamaya uygulamak, uygulama geliştiricinin oynatıcının arabelleğe alma politikasını değiştirmesine olanak tanır.Extractor
- Şu anda kitaplık tarafından desteklenmeyen bir kapsayıcı biçimini desteklemeniz gerekiyorsa özel birExtractor
sınıfı uygulayabilirsiniz.MediaSource
- Oluşturuculara özel bir şekilde beslenecek medya örnekleri almak veya özelMediaSource
birleştirme davranışı uygulamak istiyorsanız özelMediaSource
sınıfı uygulamak uygun olabilir.MediaSource.Factory
: Özel birMediaSource.Factory
uygulamaya uygulandığında, uygulamanın birMediaItem
'denMediaSource
oluşturma şeklini özelleştirmesine olanak tanır.DataSource
: ExoPlayer'ın yayın paketi, farklı kullanım alanları için zaten bir diziDataSource
uygulaması içerir. Verileri özel bir protokol üzerinden, özel bir HTTP yığını kullanarak veya özel bir kalıcı önbellekten yüklemek için kendiDataSource
sınıfınızı uygulamak isteyebilirsiniz.
Özel bileşenler oluştururken aşağıdakileri öneririz:
- Özel bir bileşenin etkinlikleri uygulamaya geri bildirmesi gerekiyorsa bunu mevcut ExoPlayer bileşenleriyle aynı modeli kullanarak yapmanızı öneririz. Örneğin,
EventDispatcher
sınıflarını kullanarak veya bir dinleyiciyle birlikte birHandler
'i bileşenin kurucusuna ileterek. - Özel bileşenlerin, oynatma sırasında uygulama tarafından yeniden yapılandırmaya olanak tanımak için mevcut ExoPlayer bileşenleriyle aynı modeli kullanmasını öneririz. Bunu yapmak için özel bileşenler
PlayerMessage.Target
'ü uygulamalı vehandleMessage
yönteminde yapılandırma değişikliklerini almalıdır. Uygulama kodu, ExoPlayer'ıncreateMessage
yöntemini çağırarak, mesajı yapılandırarak vePlayerMessage.send
kullanarak bileşene göndererek yapılandırma değişikliklerini iletmelidir. Oynatma iş akışında yayınlanacak mesajların gönderilmesi, bu mesajların oynatıcıda gerçekleştirilen diğer işlemlerle birlikte sırayla yürütülmesini sağlar.