ExoPlayer kitaplığının temelinde Player
arayüzü yer alır. Player
; medya arabelleğe alma, oynatma, duraklatma ve arama gibi geleneksel üst düzey medya oynatıcı işlevleri sunar. Varsayılan uygulama ExoPlayer
, oynatılan medya türü, nasıl, nerede saklandığı ve nasıl oluşturulduğu hakkında az varsayımda bulunmak (ve dolayısıyla birkaç kısıtlama getirmek) üzere tasarlanmıştır. Medya yükleme ve oluşturma işlemlerini doğrudan uygulamak yerine, ExoPlayer
uygulamaları bu işi bir oynatıcı oluşturulduğunda veya oynatıcıya yeni medya kaynakları aktarıldığında yerleştirilen bileşenlere atar.
Tüm ExoPlayer
uygulamalarında ortak olan bileşenler:
- Oynatılacak medyayı tanımlayan, medyayı yükleyen ve yüklenen medyanın okunabileceği
MediaSource
örnekleri. Oynatıcının içindeki birMediaSource.Factory
tarafındanMediaItem
öğesinden birMediaSource
örneği oluşturulur. Ayrıca, medya kaynağı tabanlı oynatma listesi API'si kullanılarak doğrudan oynatıcıya da iletilebilir. MediaItem
öğesiniMediaSource
öğesine dönüştürenMediaSource.Factory
örnekleri. Oynatıcı oluşturulduğundaMediaSource.Factory
eklenir.- Medyanın bağımsız bileşenlerini oluşturan
Renderer
örnekleri. Bunlar, oynatıcı oluşturulduğunda eklenir. MediaSource
tarafından sağlanan ve mevcut herRenderer
tarafından kullanılacak parçaları seçen birTrackSelector
. Oynatıcı oluşturulduğunda birTrackSelector
yerleştirilir.MediaSource
öğesinin ne zaman daha fazla medya arabelleğe alacağını ve ne kadar medyanın arabelleğe alınacağını kontrol eden birLoadControl
. Oynatıcı oluşturulduğunda birLoadControl
yerleştirilir.- Oynatıcının yapılandırılmış bir canlı ofsete yakın kalmasını sağlamak için canlı oynatmalar sırasında oynatma hızını kontrol eden
LivePlaybackSpeedControl
. Oynatıcı oluşturulduğunda birLivePlaybackSpeedControl
yerleştirilir.
Oynatıcı işlevi parçaları uygulayan bileşenleri ekleme kavramı kitaplık genelinde mevcuttur. Bazı bileşenlerin varsayılan uygulamaları, yapılan başka yerleştirilen bileşenlere iş yetkisi verir. Bu, birçok alt bileşenin, özel bir şekilde yapılandırılan uygulamalarla tek tek değiştirilmesine olanak tanır.
Oynatıcı özelleştirme
Bileşenleri yerleştirerek oynatıcıyı özelleştirmeyle ilgili yaygın örneklerden bazıları 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 ile ilgili bir sayfamız bulunmaktadır.
Ağdan yüklenen verileri önbelleğe alma
Anında önbelleğe alma ve medya indirme kılavuzlarına bakın.
Sunucu etkileşimlerini özelleştirme
Bazı uygulamalar HTTP isteklerine ve yanıtlarına müdahale etmek isteyebilir. Özel istek başlıkları eklemek, sunucunun yanıt başlıklarını okumak, isteklerin URI'larını değiştirmek vb. işlemler isteyebilirsiniz. Örneğin, uygulamanız medya segmentlerini isterken başlık olarak bir jeton ekleyerek kendi kimliğini doğrulayabilir.
Aşağıdaki örnek, DefaultMediaSourceFactory
içine özel bir DataSource.Factory
ekleyerek bu davranışların nasıl uygulanacağını göstermektedir:
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, eklenen HttpDataSource
her HTTP isteğine "Header: Value"
üst bilgisini içerir. Bu davranış, bir HTTP kaynağıyla her etkileşim için düzeltilir.
Daha ayrıntılı bir yaklaşım için ResolvingDataSource
kullanarak tam zamanında davranış ekleyebilirsiniz. Aşağıdaki kod snippet'i, istek üstbilgilerinin bir HTTP kaynağıyla etkileşim kurmadan hemen önce nasıl ekleneceğini göstermektedir:
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)));
Ayrıca, aşağıdaki snippet'te gösterildiği gibi URI'da tam zamanında değişiklikler yapmak için bir 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şlemeyi özelleştirme
Özel bir LoadErrorHandlingPolicy
uygulamak, uygulamaların ExoPlayer'ın yükleme hatalarına tepki verme şeklini özelleştirmesine olanak tanır. Örneğin, bir uygulama birçok kez yeniden denemek yerine hızlı bir şekilde başarısız olmak 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'te özel geri yükleme mantığının nasıl uygulanacağı gösterilmektedir:
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, tek tek biçimlerin progresif medyadan kaldırılma şeklini özelleştirmek için kullanılabilir. Bunlar, DefaultMediaSourceFactory
için sağlanan DefaultExtractorsFactory
öğesinde ayarlanabilir. Aşağıdaki örnek, MP3 akışları için dizine dayalı aramayı etkinleştiren bir işaret iletir.
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ıyla sarmalama sağlama
MP3, ADTS ve AMR akışlarında 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çıklandığı gibi bağımsız DefaultExtractorsFactory.setXyzExtractorFlags
yöntemleri kullanılarak 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
kullanın.
Kotlin
val extractorsFactory = DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true)
Java
DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
Ardından ExtractorsFactory
, yukarıda ayıklayıcı işaretlerini özelleştirmek için açıklandığı gibi DefaultMediaSourceFactory
aracılığıyla eklenebilir.
Eşzamansız arabellek kuyruğunu etkinleştirme
Eşzamansız arabellek kuyruğuna ekleme, ExoPlayer'ın oluşturma ardışık düzenindeki bir geliştirmedir. Bu özellik, MediaCodec
örneklerini eşzamansız modda çalıştırır ve verilerin kod çözmeyi ve işlenmesini planlamak için ek iş parçacıkları kullanır. Bu özelliği etkinleştirmek kare atlamalarını ve ses eksikliğini azaltabilir.
Eşzamansız arabellek kuyruğu oluşturma özelliği, Android 12 (API düzeyi 31) ve sonraki sürümleri çalıştıran cihazlarda varsayılan olarak etkindir. Android 6.0 (API düzeyi 23) sürümünden itibaren ise manuel olarak etkinleştirilebilir. Özellikle DRM korumalı veya yüksek kare hızlı içerikleri oynatırken, karelerin düştüğünü veya sesin azaldığını gözlemlediğiniz belirli cihazlarda bu özelliği etkinleştirmeyi düşünün.
En basit durumda, oynatıcıya aşağıdaki şekilde 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 örnekliyorsanız MediaCodecVideoRenderer
ve MediaCodecAudioRenderer
kurucularına bir AsynchronousMediaCodecAdapter.Factory
iletin.
ForwardingPlayer
ile yöntem çağrılarına müdahale ediliyor
Bir Player
örneğinin davranışını, ForwardingPlayer
alt sınıfında sarmalayarak ve yöntemleri geçersiz kılarak aşağıdakilerden birini yapabilirsiniz:
- Parametrelere, yetki verilmiş
Player
kullanıcısına iletmeden önce erişin. - Döndürmeden önce, yetki verilmiş
Player
tarafından döndürülen değere erişin. - Yöntemi tamamen yeniden uygulayın.
ForwardingPlayer
yöntemlerini geçersiz kılarken, özellikle aynı veya ilgili davranışa sahip yöntemleri ele alırken uygulamanın kendinden tutarlı ve Player
arayüzüyle uyumlu kalmasını sağlamak çok önemlidir. Örneğin:
- Her "oynat" işlemini geçersiz kılmak istiyorsanız hem
ForwardingPlayer.play
hem deForwardingPlayer.setPlayWhenReady
değerlerini geçersiz kılmanız gerekir. Çünkü arayan,playWhenReady = true
olduğunda bu yöntemlerin davranışlarının aynı olmasını bekler. - İleri sarma artışını değiştirmek isterseniz özelleştirilmiş artışınızla arama yapmak için
ForwardingPlayer.seekForward
değerini ve arayana doğru özelleştirilmiş artışı bildirmek içinForwardingPlayer.getSeekForwardIncrement
değerini geçersiz kılmanız gerekir. - Bir oynatıcı örneği tarafından hangi
Player.Commands
için reklam yayınlandığını kontrol etmek isterseniz hemPlayer.getAvailableCommands()
hem dePlayer.isCommandAvailable()
öğelerini geçersiz kılmanız ve temel oynatıcıdan gelen değişikliklerden haberdar olmak içinPlayer.Listener.onAvailableCommandsChanged()
geri çağırmasını dinlemeniz gerekir.
MediaSource özelleştirmesi
Yukarıdaki örneklerde, oynatıcıya geçirilen tüm MediaItem
nesnelerinin oynatılması sırasında kullanılmak üzere özelleştirilmiş bileşenler eklenir. Ayrıntılı özelleştirmenin gerekli olduğu durumlarda, özelleştirilmiş bileşenleri doğrudan oynatıcıya iletilebilecek ayrı MediaSource
örneklerine de ekleyebilirsiniz. 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 üst kısmında 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 oluşturulabilir. Özel uygulamaların 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
– ÖzelTrackSelector
uygulamak, uygulama geliştiricilerin,MediaSource
tarafından sunulan kanalların mevcutRenderer
'lerin her biri tarafından tüketilmek üzere seçilme şeklini değiştirmesine olanak tanır.LoadControl
– Özel birLoadControl
uygulamak, uygulama geliştiricisinin 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ı uygulamayı düşünebilirsiniz.MediaSource
– Medya örneklerini oluşturuculara özel bir şekilde beslemek veya özelMediaSource
birleştirme davranışı uygulamak istiyorsanız özel birMediaSource
sınıfı uygulamak uygun olabilir.MediaSource.Factory
– Özel birMediaSource.Factory
uygulamak, bir uygulamanınMediaItem
öğesindenMediaSource
oluşturma şeklini özelleştirmesine olanak tanır.DataSource
: ExoPlayer'ın yukarı akış paketi, farklı kullanım alanları için halihazırda bir diziDataSource
uygulaması içermektedir. Verileri özel bir protokol üzerinden, özel bir HTTP yığını kullanarak veya özel bir kalıcı önbellekten başka bir şekilde yüklemek için kendiDataSource
sınıfınızı uygulamak isteyebilirsiniz.
Özel bileşenler oluştururken aşağıdakileri yapmanızı öneririz:
- Bir özel bileşenin etkinlikleri uygulamaya geri bildirmesi gerekiyorsa bunu mevcut ExoPlayer bileşenleriyle aynı modeli kullanarak yapmanızı (örneğin,
EventDispatcher
sınıflarını kullanarak veya bileşeni oluşturan oluşturucuya bir işleyiciyle birlikte birHandler
geçirerek) öneririz. - Oynatma sırasında uygulamanın yeniden yapılandırılmasına olanak tanımak için özel bileşenlerin mevcut ExoPlayer bileşenleriyle aynı modeli kullanmalarını öneririz. Bunu yapmak için özel bileşenlerin
PlayerMessage.Target
uygulaması vehandleMessage
yönteminde yapılandırma değişiklikleri alması gerekir. Uygulama kodu, yapılandırma değişikliklerini ExoPlayer'ıncreateMessage
yöntemini çağırarak, mesajı yapılandırarak vePlayerMessage.send
ile bileşene göndererek geçmelidir. Oynatma iş parçacığında teslim edilecek mesajların gönderilmesi, mesajların oynatıcıda gerçekleştirilen diğer işlemlerle birlikte sırayla yürütülmesini sağlar.