สแต็กเครือข่าย

ExoPlayer มักใช้สําหรับสตรีมมิงสื่อผ่านอินเทอร์เน็ต รองรับ สแต็กเครือข่ายหลายรายการเพื่อสร้างคำขอเครือข่ายที่สำคัญ ตัวเลือกของคุณ ของสแต็กเครือข่ายอาจส่งผลกระทบอย่างมากต่อประสิทธิภาพการสตรีม

หน้านี้จะอธิบายวิธีกำหนดค่า ExoPlayer ให้ใช้สแต็กเครือข่ายที่ต้องการ แสดงรายการตัวเลือกที่ใช้ได้ ให้คำแนะนำเกี่ยวกับวิธีเลือกสแต็กเครือข่ายสำหรับแอป และอธิบายวิธีเปิดใช้การแคชสำหรับสื่อที่สตรีม

การกำหนดค่า ExoPlayer เพื่อใช้สแต็กเครือข่ายที่เฉพาะเจาะจง

ExoPlayer จะโหลดข้อมูลผ่านคอมโพเนนต์ DataSource ซึ่งได้รับจากอินสแตนซ์ DataSource.Factory ที่แทรกจากโค้ดแอป

หากแอปของคุณเล่นได้เฉพาะเนื้อหา http(s) การเลือกสแต็กเครือข่ายนั้นง่ายเพียงอัปเดตอินสแตนซ์ DataSource.Factory ที่แอปของคุณแทรกให้เป็นอินสแตนซ์ของ HttpDataSource.Factory ที่สอดคล้องกับสแต็กเครือข่ายที่ต้องการใช้ หากแอปของคุณ ต้องเล่นเนื้อหาที่ไม่ใช่ http เช่น ไฟล์ในเครื่อง DefaultDataSource.Factory:

Kotlin

DefaultDataSource.Factory(
  ...
  /* baseDataSourceFactory= */ PreferredHttpDataSource.Factory(...))

Java

new DefaultDataSource.Factory(
    ...
    /* baseDataSourceFactory= */ new PreferredHttpDataSource.Factory(...));

ในตัวอย่างนี้ PreferredHttpDataSource.Factory คือโรงงานที่สอดคล้องกับสแต็กเครือข่ายที่ต้องการ เลเยอร์ DefaultDataSource.Factory ช่วยเพิ่มการสนับสนุน สำหรับแหล่งข้อมูลที่ไม่ใช่ http เช่น ไฟล์ในเครื่อง

ตัวอย่างต่อไปนี้แสดงวิธีสร้าง ExoPlayer ที่จะใช้สแต็กเครือข่าย Cronet และรองรับการเล่นเนื้อหาที่ไม่ใช่ http(s) ด้วย

Kotlin

// Given a CronetEngine and Executor, build a CronetDataSource.Factory.
val cronetDataSourceFactory = CronetDataSource.Factory(cronetEngine, executor)

// Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds
// in support for requesting data from other sources (such as files, resources,
// etc).
val dataSourceFactory =
  DefaultDataSource.Factory(context, /* baseDataSourceFactory= */ cronetDataSourceFactory)

// Inject the DefaultDataSource.Factory when creating the player.
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory)
    )
    .build()

Java

// Given a CronetEngine and Executor, build a CronetDataSource.Factory.
CronetDataSource.Factory cronetDataSourceFactory =
    new CronetDataSource.Factory(cronetEngine, executor);

// Wrap the CronetDataSource.Factory in a DefaultDataSource.Factory, which adds
// in support for requesting data from other sources (such as files, resources,
// etc).
DefaultDataSource.Factory dataSourceFactory =
    new DefaultDataSource.Factory(
        context, /* baseDataSourceFactory= */ cronetDataSourceFactory);

// Inject the DefaultDataSource.Factory when creating the player.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory))
        .build();

สแต็กเครือข่ายที่รองรับ

ExoPlayer รองรับ HttpEngine, Cronet, OkHttp และสแต็กเครือข่ายเริ่มต้นที่ติดตั้งมาในตัวของ Android โดยตรง นอกจากนี้ยังสามารถขยาย ExoPlayer เพื่อรองรับ สแต็กเครือข่ายอื่นๆ ที่ใช้งานได้ใน Android

HttpEngine

HttpEngine เป็นกองซ้อนเครือข่ายเริ่มต้นที่แนะนำใน Android ตั้งแต่ API 34 (หรือส่วนขยาย S 7) ในกรณีส่วนใหญ่ โมเดลจะใช้สแต็กเครือข่าย Cronet ภายใน รองรับ HTTP, HTTP/2 และ HTTP/3 ผ่านโปรโตคอล QUIC

ExoPlayer รองรับ HttpEngine ด้วย HttpEngineDataSource.Factory คุณสามารถแทรกแท็บเล็ตแหล่งข้อมูลนี้ตามที่อธิบายไว้ในการกำหนดค่า ExoPlayer ให้ใช้สแต็กเครือข่ายที่เฉพาะเจาะจง

Cronet

Cronet คือสแต็กเครือข่าย Chromium ที่พร้อมให้บริการแก่แอป Android เป็นไลบรารี Cronet ใช้เทคโนโลยีหลายอย่างเพื่อลดเวลาในการตอบสนองและเพิ่มปริมาณงานของคำขอเครือข่ายที่แอปของคุณต้องใช้ในการทำงาน ซึ่งรวมถึงคำขอที่สร้างขึ้นโดย ExoPlayer โดยรองรับโปรโตคอล HTTP, HTTP/2 และ HTTP/3 ผ่าน QUIC โดยกำเนิด แอปสตรีมมิงขนาดใหญ่บางแอปในโลก รวมถึง YouTube ใช้ Cronet

ExoPlayer รองรับ Cronet ผ่าน ไลบรารี Cronet ดูวิธีการโดยละเอียดในREADME.mdของคลัง โปรดทราบว่าไลบรารี Cronet สามารถใช้การติดตั้งใช้งาน Cronet พื้นฐาน 3 รายการต่อไปนี้

  1. บริการ Google Play: เราขอแนะนำให้ใช้การติดตั้งใช้งานนี้ในเกือบทุกกรณี และเปลี่ยนไปใช้สแต็กเครือข่ายในตัวของ Android (DefaultHttpDataSource) หากบริการ Google Play ไม่พร้อมใช้งาน
  2. Cronet Embedded: อาจเป็นทางเลือกที่ดีหากผู้ใช้จำนวนมาก อยู่ในตลาดที่บริการ Google Play ไม่พร้อมให้บริการอย่างกว้างขวาง หรือหากคุณ ต้องการควบคุมเวอร์ชันที่แน่นอนของการใช้งาน Cronet ที่กำลังใช้อยู่ ข้อเสียหลักของ Cronet Embedded คือเพิ่มประมาณ 8 MB แอปของคุณ
  3. ทางเลือกสำรองของ Cronet: การใช้งานสำรองของ Cronet API ของ Cronet เป็นพื้นที่โดยรอบของสแต็กเครือข่ายในตัวของ Android ควร จะไม่ใช้กับ ExoPlayer เนื่องจากใช้สแต็กเครือข่ายในตัวของ Android โดยตรง (โดยใช้ DefaultHttpDataSource) จะมีประสิทธิภาพมากกว่า

OkHttp

OkHttp เป็นแพ็กเกจสแต็กเครือข่ายสมัยใหม่อีกแพ็กเกจหนึ่งที่แอป Android ยอดนิยมจำนวนมากใช้กันอย่างแพร่หลาย โดยรองรับ HTTP และ HTTP/2 แต่ยังไม่รองรับ HTTP/3 ผ่าน QUIC

ExoPlayer รองรับ OkHttp ผ่านคลัง OkHttp ดูวิธีการโดยละเอียดในREADME.mdของคลัง เมื่อใช้ไลบรารี OkHttp สแต็กเครือข่ายจะถูกฝังอยู่ภายใน แอป ซึ่งคล้ายกับ Cronet Embedded แต่ OkHttp มีความสำคัญ ที่มีขนาดเล็กลง ทำให้แอปมีขนาดน้อยกว่า 1 MB

สแต็กเครือข่ายในตัวของ Android

ExoPlayer รองรับการใช้สแต็กเครือข่ายในตัวของ Android DefaultHttpDataSource และ DefaultHttpDataSource.Factory ซึ่งเป็นส่วนหนึ่งของ ไลบรารีหลักของ ExoPlayer

การใช้งานสแต็กเครือข่ายที่แน่นอนจะขึ้นอยู่กับซอฟต์แวร์ที่ทำงานบน อุปกรณ์ที่เกี่ยวข้อง อุปกรณ์ส่วนใหญ่รองรับเฉพาะ HTTP เท่านั้น (กล่าวคือ ระบบไม่รองรับ HTTP/2 และ HTTP/3 ผ่าน QUIC)

สแต็กเครือข่ายอื่นๆ

นอกจากนี้ แอปยังผสานรวมสแต็กเครือข่ายอื่นๆ กับ ExoPlayer ได้ด้วย โดยใช้ HttpDataSource ที่รวมกลุ่มเครือข่าย พร้อมด้วย HttpDataSource.Factory ที่เกี่ยวข้อง ไลบรารี Cronet และ OkHttp ของ ExoPlayer เป็นตัวอย่างที่ดีของวิธีดำเนินการนี้

เมื่อผสานรวมกับสแต็กเครือข่าย Java ล้วน ขอแนะนำว่า DataSourceContractTestเพื่อตรวจสอบว่าการใช้งาน HttpDataSource ของคุณ ทำงานได้อย่างถูกต้อง OkHttpDataSourceContractTest ในไลบรารี OkHttp คือ ตัวอย่างที่ดีของวิธีการนี้

การเลือกสแต็กเครือข่าย

ตารางต่อไปนี้แสดงข้อดีและข้อเสียของสแต็กเครือข่ายที่ ExoPlayer รองรับ

สแต็กเครือข่าย โปรโตคอล ผลกระทบของขนาด APK หมายเหตุ
HttpEngine HTTP
HTTP/2
HTTP/3 ผ่าน QUIC
ไม่มี ใช้ได้กับ API 34 หรือส่วนขยาย S 7 เท่านั้น
Cronet (บริการ Google Play) HTTP
HTTP/2
HTTP/3 ผ่าน QUIC
เล็ก
(<100KB)
ต้องใช้บริการ Google Play อัปเดตเวอร์ชัน Cronet โดยอัตโนมัติแล้ว
Cronet (แบบฝัง) HTTP
HTTP/2
HTTP/3 ผ่าน QUIC
ใหญ่
(~8 MB)
เวอร์ชัน Cronet ที่นักพัฒนาแอปควบคุม
Cronet (สำรอง) HTTP
(แตกต่างกันไปตามอุปกรณ์)
เล็ก
(<100KB)
ไม่แนะนำสำหรับ ExoPlayer
OkHttp HTTP
HTTP/2
เล็ก
(<1MB)
สแต็กเครือข่ายในตัว HTTP
(แตกต่างกันไปตามอุปกรณ์)
ไม่มี การใช้งานจะแตกต่างกันไปตามอุปกรณ์

โปรโตคอล HTTP/2 และ HTTP/3 ผ่าน QUIC ช่วยปรับปรุงประสิทธิภาพสตรีมมิงสื่อได้อย่างมาก โดยเฉพาะอย่างยิ่งเมื่อสตรีมสื่อแบบปรับเปลี่ยนได้ซึ่งเผยแพร่โดยใช้เครือข่ายนำส่งข้อมูล (CDN) อาจมีบางกรณีที่การใช้โปรโตคอลเหล่านี้ช่วยให้ CDN ทำงานได้อย่างมีประสิทธิภาพมากขึ้น ด้วยเหตุนี้ การที่ HttpEngine และ Cronet รองรับทั้ง HTTP/2 และ HTTP/3 ผ่าน QUIC (และการที่ OkHttp รองรับ HTTP/2) จึงถือเป็นข้อดีที่สำคัญเมื่อเทียบกับการใช้สแต็กเครือข่ายในตัวของ Android ในกรณีที่เซิร์ฟเวอร์ที่โฮสต์เนื้อหารองรับโปรโตคอลเหล่านี้ด้วย

เมื่อพิจารณาสตรีมมิงสื่อแยกต่างหาก เราขอแนะนำให้ใช้ HttpEngine หรือ Cronet ที่ Google Play Services มีให้ โดยจะใช้ DefaultHttpDataSource แทนหาก Google Play Services ไม่พร้อมใช้งาน คําแนะนํานี้ช่วยรักษาสมดุลระหว่างการเปิดใช้ HTTP/2 และ HTTP/3 ผ่าน QUIC ในอุปกรณ์ส่วนใหญ่ และหลีกเลี่ยงการเพิ่มขนาด APK อย่างมาก คําแนะนํานี้มีข้อยกเว้น สำหรับกรณีที่บริการ Google Play อาจไม่พร้อมให้บริการ ในอุปกรณ์จำนวนมากพอสมควรที่จะเรียกใช้แอปของคุณ การใช้ Cronet Embedded หรือ OkHttp อาจเหมาะสมกว่า การใช้สแต็กเครือข่ายในตัวอาจยอมรับได้หากขนาด APK เป็นข้อกังวลที่สำคัญ หรือหากสตรีมมิงสื่อเป็นเพียงส่วนเล็กๆ ของฟังก์ชันการทํางานของแอป

นอกเหนือจากสื่อแล้ว ปกติแล้วการเลือกสแต็กเครือข่ายเดี่ยวเป็นความคิดที่ดี สำหรับเครือข่ายทั้งหมดที่แอปของคุณให้บริการ การดำเนินการนี้ช่วยให้ทรัพยากร (เช่น ซ็อกเก็ต) เพื่อทำงานร่วมกันและใช้งานร่วมกันระหว่าง ExoPlayer กับโปรแกรมอื่นๆ ได้อย่างมีประสิทธิภาพ คอมโพเนนต์ของแอป

เนื่องจากแอปของคุณมักจะต้องใช้เครือข่ายที่ไม่เกี่ยวข้อง การเล่นสื่อ การเลือกสแต็กเครือข่ายที่คุณเลือกในท้ายที่สุด คำแนะนำด้านบนสำหรับการสตรีมสื่อแบบแยกเดี่ยว องค์ประกอบอื่นๆ ที่ทำหน้าที่เป็นเครือข่าย และความสำคัญที่สัมพันธ์กับ แอป

การแคชสื่อ

ExoPlayer รองรับการแคชไบต์ที่โหลดไปยังดิสก์เพื่อป้องกันการโหลดซ้ำๆ จำนวนไบต์เดียวกันจากเครือข่าย ซึ่งจะเป็นประโยชน์เมื่อจะกรอกลับไปยังวิดีโอปัจจุบัน สื่อหรือรายการเดียวกันซ้ำ

การแคชต้องใช้อินสแตนซ์ SimpleCache ที่ชี้ไปยังไดเรกทอรีแคชเฉพาะและ CacheDataSource.Factory

Kotlin

// Note: This should be a singleton in your app.
val databaseProvider = StandaloneDatabaseProvider(context)

// An on-the-fly cache should evict media when reaching a maximum disk space limit.
val cache =
    SimpleCache(
        downloadDirectory, LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider)

// Configure the DataSource.Factory with the cache and factory for the desired HTTP stack.
val cacheDataSourceFactory =
    CacheDataSource.Factory()
        .setCache(cache)
        .setUpstreamDataSourceFactory(httpDataSourceFactory)

// Inject the DefaultDataSource.Factory when creating the player.
val player =
    ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory))
        .build()

Java

// Note: This should be a singleton in your app.
DatabaseProvider databaseProvider = new StandaloneDatabaseProvider(context);

// An on-the-fly cache should evict media when reaching a maximum disk space limit.
Cache cache =
    new SimpleCache(
        downloadDirectory, new LeastRecentlyUsedCacheEvictor(maxBytes), databaseProvider);

// Configure the DataSource.Factory with the cache and factory for the desired HTTP stack.
DataSource.Factory cacheDataSourceFactory =
    new CacheDataSource.Factory()
        .setCache(cache)
        .setUpstreamDataSourceFactory(httpDataSourceFactory);

// Inject the DefaultDataSource.Factory when creating the player.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setDataSourceFactory(cacheDataSourceFactory))
        .build();