การแก้ปัญหา


การแก้ไขข้อผิดพลาด "ไม่อนุญาตให้มีการรับส่งข้อมูล HTTP แบบข้อความธรรมดา"

ข้อผิดพลาดนี้จะเกิดขึ้นหากแอปขอการรับส่งข้อมูล HTTP แบบข้อความธรรมดา (นั่นคือ http:// แทนที่จะเป็น https://) เมื่อการกำหนดค่าความปลอดภัยของเครือข่ายไม่อนุญาต หากแอปกำหนดเป้าหมายเป็น Android 9 (ระดับ API 28) ขึ้นไป การรับส่งข้อมูล HTTP แบบข้อความธรรมดาจะถูกปิดใช้ในการกำหนดค่าเริ่มต้น

หากแอปต้องทำงานกับการรับส่งข้อมูล HTTP แบบข้อความธรรมดา คุณจะต้องใช้การกำหนดค่าความปลอดภัยของเครือข่ายที่อนุญาต ดูรายละเอียดได้ในเอกสารประกอบเกี่ยวกับความปลอดภัยของเครือข่ายของ Android หากต้องการเปิดใช้การรับส่งข้อมูล HTTP แบบข้อความธรรมดาทั้งหมด คุณเพียงแค่เพิ่ม android:usesCleartextTraffic="true" ลงในองค์ประกอบ application ของ AndroidManifest.xml ของแอป

แอปเดโม ExoPlayer ใช้การกำหนดค่าความปลอดภัยของเครือข่ายเริ่มต้น จึงไม่อนุญาตให้มีการรับส่งข้อมูล HTTP แบบข้อความธรรมดา คุณเปิดใช้ได้โดยใช้คำแนะนำด้านบน

การแก้ไขข้อผิดพลาด "SSLHandshakeException", "CertPathValidatorException" และ "ERR_CERT_AUTHORITY_INVALID"

SSLHandshakeException, CertPathValidatorException และ ERR_CERT_AUTHORITY_INVALID ทั้งหมดบ่งบอกถึงปัญหาเกี่ยวกับใบรับรอง SSL ของเซิร์ฟเวอร์ ข้อผิดพลาดเหล่านี้ไม่ได้เกิดขึ้นเฉพาะกับ ExoPlayer ดูรายละเอียดเพิ่มเติมได้ใน เอกสารประกอบเกี่ยวกับ SSL ของ Android

เหตุใดไฟล์สื่อบางไฟล์จึงกรอไม่ได้

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

หากคุณต้องการกรอแต่มีสื่อที่กรอไม่ได้ เราขอแนะนำให้แปลงเนื้อหาให้ใช้รูปแบบคอนเทนเนอร์ที่เหมาะสมกว่า สำหรับไฟล์ MP3, ADTS และ AMR คุณยังเปิดใช้การกรอได้โดยถือว่าไฟล์มีอัตราบิต คงที่ตามที่อธิบายไว้ ที่นี่

เหตุใดการกรอในไฟล์ MP3 บางไฟล์จึงไม่แม่นยำ

ไฟล์ MP3 ที่มีบิตเรตผันแปร (VBR) ไม่เหมาะสำหรับกรณีการใช้งานที่ต้องมีการกรอที่แม่นยำ มี 2 เหตุผลดังนี้

  1. สำหรับการกรอที่แม่นยำ รูปแบบคอนเทนเนอร์ควรระบุการแมปเวลาเป็นไบต์ที่แม่นยำในส่วนหัว การแมปนี้ช่วยให้เพลเยอร์แมปเวลาที่ขอให้กรอเป็นออฟเซ็ตไบต์ที่เกี่ยวข้อง และเริ่มขอ แยกวิเคราะห์ และเล่นสื่อจากออฟเซ็ตนั้น น่าเสียดายที่ส่วนหัวที่ใช้ระบุการแมปนี้ใน MP3 (เช่น ส่วนหัว XING) มักไม่แม่นยำ
  2. สำหรับรูปแบบคอนเทนเนอร์ที่ไม่มีการแมปเวลาเป็นไบต์ที่แม่นยำ (หรือไม่มีการแมปเวลาเป็นไบต์เลย) คุณยังคงกรอได้อย่างแม่นยำหากคอนเทนเนอร์มีไทม์สแตมป์ตัวอย่างแบบสัมบูรณ์ในสตรีม ในกรณีนี้ เพลเยอร์สามารถแมปเวลาที่ขอให้กรอเป็นออฟเซ็ตไบต์ที่คาดเดาได้ดีที่สุด เริ่มขอสื่อจากออฟเซ็ตนั้น แยกวิเคราะห์ไทม์สแตมป์ตัวอย่างแบบสัมบูรณ์แรก และดำเนินการค้นหาแบบไบนารีแบบมีคำแนะนำในสื่อได้อย่างมีประสิทธิภาพจนกว่าจะพบตัวอย่างที่ถูกต้อง น่าเสียดายที่ MP3 ไม่มีไทม์สแตมป์ตัวอย่างแบบสัมบูรณ์ในสตรีม จึงไม่สามารถใช้วิธีนี้ได้

ด้วยเหตุนี้ วิธีเดียวที่จะกรอไฟล์ MP3 แบบ VBR ได้อย่างแม่นยำคือการสแกนไฟล์ทั้งหมดและสร้างการแมปเวลาเป็นไบต์ในเพลเยอร์ด้วยตนเอง คุณเปิดใช้กลยุทธ์นี้ได้โดยใช้ FLAG_ENABLE_INDEX_SEEKING, ซึ่งตั้งค่าได้ใน DefaultExtractorsFactory โดยใช้ setMp3ExtractorFlags โปรดทราบว่าวิธีนี้ไม่เหมาะกับไฟล์ MP3 ขนาดใหญ่ โดยเฉพาะอย่างยิ่งหากผู้ใช้พยายามกรอไปใกล้ส่วนท้ายของสตรีมหลังจากเริ่มเล่นได้ไม่นาน ซึ่งกำหนดให้เพลเยอร์ต้องรอจนกว่าจะดาวน์โหลดและจัดทำดัชนีสตรีมทั้งหมดก่อนที่จะกรอ ใน ExoPlayer เรา ตัดสินใจที่จะเพิ่มประสิทธิภาพความเร็วมากกว่าความแม่นยำในกรณีนี้ และ FLAG_ENABLE_INDEX_SEEKING จึงปิดใช้งานโดยค่าเริ่มต้น

หากคุณควบคุมสื่อที่กำลังเล่นได้ เราขอแนะนำให้ใช้รูปแบบคอนเทนเนอร์ที่เหมาะสมกว่า เช่น MP4 เราไม่ทราบกรณีการใช้งานที่ MP3 เป็นตัวเลือกที่ดีที่สุดสำหรับรูปแบบสื่อ

เหตุใดการกรอวิดีโอของฉันจึงช้า

เมื่อเพลเยอร์กรอไปยังตำแหน่งการเล่นใหม่ในวิดีโอ เพลเยอร์ต้องทำ 2 สิ่งต่อไปนี้

  1. โหลดข้อมูลที่ตรงกับตำแหน่งการเล่นใหม่ลงในบัฟเฟอร์ (อาจไม่จำเป็นหากข้อมูลนี้อยู่ในบัฟเฟอร์อยู่แล้ว)
  2. ล้างตัวถอดรหัสวิดีโอและเริ่มถอดรหัสจาก I-frame (คีย์เฟรม) ก่อน ตำแหน่งการเล่นใหม่ เนื่องจากมีการเข้ารหัสภายในเฟรมที่รูปแบบการบีบอัดวิดีโอส่วนใหญ่ใช้ เพื่อให้การกรอ แม่นยำ (นั่นคือ การเล่นจะเริ่มตรงตำแหน่งที่กรอ) ระบบจะต้องถอดรหัสและทิ้งเฟรมทั้งหมดระหว่าง I-frame ก่อนหน้ากับตำแหน่งที่กรอทันที (โดยไม่แสดงบนหน้าจอ)

คุณสามารถลดเวลาในการตอบสนองที่เกิดจาก (1) ได้โดยการเพิ่มปริมาณ ข้อมูลที่บัฟเฟอร์ไว้ในหน่วยความจำโดยเพลเยอร์ หรือ การแคชล่วงหน้าข้อมูลลงในดิสก์

คุณสามารถลดเวลาในการตอบสนองที่เกิดจาก (2) ได้โดยการลดความแม่นยำ ของการกรอโดยใช้ ExoPlayer.setSeekParameters หรือเข้ารหัสวิดีโอใหม่ ให้มี I-frame บ่อยขึ้น (ซึ่งจะทำให้ไฟล์เอาต์พุตมีขนาดใหญ่ขึ้น)

เหตุใดไฟล์ MPEG-TS บางไฟล์จึงเล่นไม่ได้

ไฟล์ MPEG-TS บางไฟล์ไม่มีตัวคั่นหน่วยการเข้าถึง (AUD) โดยค่าเริ่มต้น ExoPlayer อาศัย AUD เพื่อตรวจหาขอบเขตเฟรมได้อย่างรวดเร็ว ในทำนองเดียวกัน ไฟล์ MPEG-TS บางไฟล์ไม่มีคีย์เฟรม IDR โดยค่าเริ่มต้น ExoPlayer จะพิจารณาคีย์เฟรมประเภทนี้เท่านั้น

ExoPlayer จะดูเหมือนติดอยู่ในสถานะการบัฟเฟอร์เมื่อได้รับคำขอให้เล่นไฟล์ MPEG-TS ที่ไม่มี AUD หรือคีย์เฟรม IDR หากต้องการเล่นไฟล์ดังกล่าว คุณสามารถทำได้โดยใช้ FLAG_DETECT_ACCESS_UNITS และ FLAG_ALLOW_NON_IDR_KEYFRAMES ตามลำดับ คุณตั้งค่าแฟล็กเหล่านี้ได้โดยตั้งค่าใน DefaultExtractorsFactory โดยใช้ setTsExtractorFlags หรือใน DefaultHlsExtractorFactory โดยใช้ เครื่องมือสร้าง การใช้ FLAG_DETECT_ACCESS_UNITS ไม่มีผลข้างเคียงใดๆ นอกเหนือจากต้องใช้การคำนวณมากกว่าการตรวจหาขอบเขตเฟรมตาม AUD การใช้ FLAG_ALLOW_NON_IDR_KEYFRAMES อาจทำให้ภาพเสียหายชั่วคราวเมื่อเริ่มเล่นและหลังจากกรอทันทีเมื่อเล่นไฟล์ MPEG-TS บางไฟล์

เหตุใดจึงไม่พบคำบรรยายในไฟล์ MPEG-TS บางไฟล์

ไฟล์ MPEG-TS บางไฟล์มีแทร็ก CEA-608 แต่ไม่ได้ประกาศแทร็กเหล่านี้ในข้อมูลเมตาของคอนเทนเนอร์ ExoPlayer จึงตรวจหาแทร็กเหล่านี้ไม่ได้ คุณระบุแทร็กคำบรรยายด้วยตนเองได้โดยระบุรายการรูปแบบคำบรรยายที่คาดไว้ให้กับ DefaultExtractorsFactory ซึ่งรวมถึงช่องการช่วยเหลือพิเศษที่ใช้ระบุแทร็กคำบรรยายในสตรีม MPEG-TS ได้

Kotlin

val extractorsFactory =
  DefaultExtractorsFactory()
    .setTsSubtitleFormats(
      listOf(
        Format.Builder()
          .setSampleMimeType(MimeTypes.APPLICATION_CEA608)
          .setAccessibilityChannel(accessibilityChannel)
          // Set other subtitle format info, such as language.
          .build()
      )
    )
val player: Player =
  ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, extractorsFactory)).build()

Java

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory()
        .setTsSubtitleFormats(
            ImmutableList.of(
                new Format.Builder()
                    .setSampleMimeType(MimeTypes.APPLICATION_CEA608)
                    .setAccessibilityChannel(accessibilityChannel)
                    // Set other subtitle format info, such as language.
                    .build()));
Player player =
    new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, extractorsFactory))
        .build();

เหตุใดไฟล์ MP4/FMP4 บางไฟล์จึงเล่นไม่ถูกต้อง

ไฟล์ MP4/FMP4 บางไฟล์มีรายการแก้ไขที่เขียนไทม์ไลน์สื่อใหม่โดยข้าม ย้าย หรือทำซ้ำรายการตัวอย่าง ExoPlayer รองรับการใช้รายการแก้ไขบางส่วน เช่น สามารถหน่วงเวลาหรือทำซ้ำกลุ่มตัวอย่างที่เริ่มต้นในตัวอย่างการซิงโครไนซ์ แต่จะไม่ตัดตัวอย่างเสียงหรือสื่อ preroll สำหรับการแก้ไขที่ไม่ได้เริ่มต้นในตัวอย่างการซิงโครไนซ์

หากพบว่าสื่อบางส่วนขาดหายไปหรือทำซ้ำโดยไม่คาดคิด ให้ลองตั้งค่า Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS หรือ FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS ซึ่งจะทำให้ ตัวแยกวิเคราะห์ละเว้นรายการแก้ไขทั้งหมด คุณตั้งค่าเหล่านี้ได้ใน โดยใช้ setMp4ExtractorFlags หรือ setFragmentedMp4ExtractorFlagsDefaultExtractorsFactory

เหตุใดสตรีมบางรายการจึงแสดงผลไม่สำเร็จด้วยโค้ดตอบกลับ HTTP 301 หรือ 302

รหัสการตอบกลับ HTTP 301 และ 302 ทั้งคู่บ่งบอกถึงการเปลี่ยนเส้นทาง ดูคำอธิบายสั้นๆ ได้ใน Wikipedia เมื่อ ExoPlayer ส่งคำขอและได้รับการตอบกลับที่มีรหัสสถานะ 301 หรือ 302 โดยปกติแล้ว ExoPlayer จะเปลี่ยนเส้นทางและเริ่มเล่นตามปกติ กรณีเดียวที่การดำเนินการนี้ไม่เกิดขึ้นโดยค่าเริ่มต้นคือการเปลี่ยนเส้นทางข้ามโปรโตคอล การเปลี่ยนเส้นทางข้ามโปรโตคอลคือการเปลี่ยนเส้นทางจาก HTTPS เป็น HTTP หรือในทางกลับกัน (หรือระหว่างโปรโตคอลคู่อื่นๆ ซึ่งพบได้น้อยกว่า) คุณสามารถทดสอบว่า URL ทำให้เกิดการเปลี่ยนเส้นทางข้ามโปรโตคอลหรือไม่โดยใช้ เครื่องมือบรรทัดคำสั่ง wget ดังนี้

wget "https://yourserver.example.com/test.mp3" 2>&1  | grep Location

เอาต์พุตควรมีลักษณะดังนี้

Location: https://secondserver.example.net/test.mp3 [following]
Location: http://thirdserver.example.org/test.mp3 [following]

ในตัวอย่างนี้มีการเปลี่ยนเส้นทาง 2 รายการ การเปลี่ยนเส้นทางแรกคือจาก https://yourserver.example.com/test.mp3 ไปยัง https://secondserver.example.net/test.mp3 ทั้งคู่เป็น HTTPS จึงไม่ใช่การเปลี่ยนเส้นทางข้ามโปรโตคอล การเปลี่ยนเส้นทางที่ 2 คือจาก https://secondserver.example.net/test.mp3 ไปยัง http://thirdserver.example.org/test.mp3 การเปลี่ยนเส้นทางนี้เป็นการเปลี่ยนเส้นทางจาก HTTPS เป็น HTTP จึงเป็นการเปลี่ยนเส้นทางข้ามโปรโตคอล ExoPlayer จะไม่เปลี่ยนเส้นทางนี้ในการกำหนดค่าเริ่มต้น ซึ่งหมายความว่าการเล่นจะแสดงผลไม่สำเร็จ

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

เหตุใดสตรีมบางรายการจึงแสดงผลไม่สำเร็จด้วย UnrecognizedInputFormatException

คำถามนี้เกี่ยวข้องกับการเล่นที่แสดงผลไม่สำเร็จในรูปแบบต่อไปนี้

UnrecognizedInputFormatException: None of the available extractors
(MatroskaExtractor, FragmentedMp4Extractor, ...) could read the stream.

ความล้มเหลวนี้อาจเกิดจาก 2 สาเหตุ สาเหตุที่พบบ่อยที่สุดคือคุณพยายามเล่นเนื้อหา DASH (mpd), HLS (m3u8) หรือ SmoothStreaming (ism, isml) แต่เพลเยอร์พยายามเล่นเป็นสตรีมแบบโปรเกรสซีฟ หากต้องการเล่นสตรีมดังกล่าว คุณต้องขึ้นต่อกันกับโมดูล ExoPlayer ที่เกี่ยวข้อง ในกรณีที่ URI ของสตรีมไม่ลงท้ายด้วยนามสกุลไฟล์มาตรฐาน คุณยังส่ง MimeTypes.APPLICATION_MPD, MimeTypes.APPLICATION_M3U8 หรือ MimeTypes.APPLICATION_SS ไปยัง setMimeType ของ MediaItem.Builder เพื่อระบุประเภทสตรีมอย่างชัดเจนได้ด้วย

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

เหตุใด setPlaybackParameters จึงทำงานไม่ถูกต้องในอุปกรณ์บางเครื่อง

เมื่อเรียกใช้บิลด์การแก้ไขข้อบกพร่องของแอปใน Android M และเวอร์ชันก่อนหน้า คุณอาจพบประสิทธิภาพการทำงานที่ไม่ราบรื่น อาร์ติแฟกต์ที่ได้ยิน และการใช้ CPU สูงเมื่อใช้ API setPlaybackParameters เนื่องจากระบบปิดใช้การเพิ่มประสิทธิภาพที่สำคัญต่อ API นี้สำหรับบิลด์ดีบักที่ทำงานใน Android เวอร์ชันดังกล่าว

โปรดทราบว่าปัญหานี้ส่งผลต่อบิลด์ดีบักเท่านั้น โดย ไม่ ส่งผลต่อบิลด์รีลีส ซึ่งระบบจะเปิดใช้การเพิ่มประสิทธิภาพเสมอ ดังนั้น รีลีสที่คุณมอบให้ผู้ใช้ปลายทางจึงไม่ควรได้รับผลกระทบจากปัญหานี้

ข้อผิดพลาด "Player is accessed on the wrong thread" หมายความว่าอย่างไร

ดูหมายเหตุเกี่ยวกับการทำงานแบบมัลติเธรดในหน้าเริ่มต้นใช้งาน

ฉันจะแก้ไขข้อผิดพลาด "Unexpected status line: ICY 200 OK" ได้อย่างไร

ปัญหานี้อาจเกิดขึ้นหากการตอบกลับของเซิร์ฟเวอร์มีบรรทัดสถานะ ICY แทนที่จะเป็นบรรทัดที่สอดคล้องกับ HTTP บรรทัดสถานะ ICY เลิกใช้งานแล้วและไม่ควรใช้ ดังนั้นหากคุณควบคุมเซิร์ฟเวอร์ได้ คุณควรจะอัปเดตเซิร์ฟเวอร์เพื่อให้การตอบกลับสอดคล้องกับ HTTP หากทำไม่ได้ การใช้ ไลบรารี ExoPlayer OkHttp จะช่วยแก้ปัญหาได้ เนื่องจากไลบรารีนี้จัดการบรรทัดสถานะ ICY ได้อย่างถูกต้อง

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

คุณสามารถค้นหาวิธี isCurrentWindowLive ของเพลเยอร์ นอกจากนี้ คุณ ยังตรวจสอบ isCurrentWindowDynamic เพื่อดูว่าหน้าต่างเป็นแบบไดนามิก (นั่นคือ ยังคงอัปเดตอยู่เรื่อยๆ) หรือไม่

ฉันจะเล่นเสียงต่อไปได้อย่างไรเมื่อแอปของฉันทำงานอยู่เบื้องหลัง

ทำตามขั้นตอนต่อไปนี้เพื่อให้แน่ใจว่าเสียงจะเล่นต่อไปเมื่อแอปทำงานอยู่เบื้องหลัง

  1. คุณต้องมีบริการที่ทำงานอยู่เบื้องหน้า ซึ่งจะป้องกันไม่ให้ระบบหยุดกระบวนการของคุณเพื่อเพิ่มทรัพยากร
  2. คุณต้องเก็บ WifiLock และ WakeLock ไว้ เพื่อให้แน่ใจว่าระบบจะเปิดวิทยุ WiFi และ CPU ไว้ คุณทำได้ง่ายๆ หากใช้ ExoPlayer โดยเรียกใช้ setWakeMode ซึ่งจะรับและปล่อยการล็อกที่จำเป็นโดยอัตโนมัติ ตามเวลาที่เหมาะสม

คุณต้องปล่อยการล็อก (หากไม่ได้ใช้ setWakeMode) และหยุดบริการทันทีที่ไม่มีการเล่นเสียงอีกต่อไป

เหตุใด ExoPlayer จึงรองรับเนื้อหาของฉัน แต่ไลบรารี ExoPlayer Cast ไม่รองรับ

เนื้อหาที่คุณพยายามเล่นอาจไม่ได้ เปิดใช้ CORS เฟรมเวิร์ก Cast กำหนดให้เนื้อหาต้องเปิดใช้ CORS จึงจะเล่นได้

เหตุใดเนื้อหาจึงเล่นไม่สำเร็จ แต่ไม่มีข้อผิดพลาดปรากฏขึ้น

อุปกรณ์ที่คุณเล่นเนื้อหาอาจไม่รองรับรูปแบบตัวอย่างสื่อที่เฉพาะเจาะจง คุณยืนยันได้ง่ายๆ โดยเพิ่ม EventLogger เป็น Listener ให้กับเพลเยอร์ และมองหาบรรทัด ที่คล้ายกับบรรทัดต่อไปนี้ใน Logcat

[ ] Track:x, id=x, mimeType=mime/type, ... , supported=NO_UNSUPPORTED_TYPE

NO_UNSUPPORTED_TYPE หมายความว่าอุปกรณ์ไม่สามารถถอดรหัสรูปแบบตัวอย่างสื่อที่ระบุโดย mimeType ได้ ดูข้อมูลเกี่ยวกับรูปแบบตัวอย่างที่รองรับได้ในเอกสารประกอบเกี่ยวกับรูปแบบสื่อของ Android media formats หัวข้อฉันจะโหลดไลบรารีการถอดรหัสเพื่อใช้ในการเล่นได้อย่างไรก็อาจเป็นประโยชน์เช่นกัน

ฉันจะโหลดไลบรารีการถอดรหัสเพื่อใช้ในการเล่นได้อย่างไร

  • ไลบรารีตัวถอดรหัสส่วนใหญ่มีขั้นตอนด้วยตนเองในการตรวจสอบและสร้างทรัพยากร Dependency ดังนั้นโปรดตรวจสอบว่าคุณได้ทำตามขั้นตอนใน README ของไลบรารีที่เกี่ยวข้องแล้ว ตัวอย่างเช่น สำหรับไลบรารี ExoPlayer FFmpeg คุณต้องทำตาม คำแนะนำใน libraries/decoder_ffmpeg/README.md ซึ่งรวมถึงการส่ง แฟล็กการกำหนดค่าเพื่อ เปิดใช้ตัวถอดรหัส สำหรับรูปแบบที่ต้องการเล่น
  • สำหรับไลบรารีที่มีโค้ดแบบเนทีฟ โปรดตรวจสอบว่าคุณใช้ Android NDK เวอร์ชันที่ถูกต้องตามที่ระบุไว้ใน README และคอยดูข้อผิดพลาดที่ปรากฏขึ้นระหว่างการกำหนดค่าและการสร้าง คุณควรเห็นไฟล์ .so ปรากฏในไดเรกทอรีย่อย libs ของเส้นทางไลบรารีสำหรับสถาปัตยกรรมที่รองรับแต่ละรายการหลังจากทำตามขั้นตอนใน README
  • หากต้องการลองเล่นโดยใช้ไลบรารีในแอปพลิเคชันเดโม โปรดดู การเปิดใช้ตัวถอดรหัสที่รวมไว้ ดูคำแนะนำในการใช้ไลบรารีจากแอปของคุณเองได้ใน README ของไลบรารี
  • หากใช้ DefaultRenderersFactory คุณควรเห็นบรรทัดบันทึกระดับข้อมูล เช่น "Loaded FfmpegAudioRenderer" ใน Logcat เมื่อตัวถอดรหัสโหลด หากไม่เห็นบรรทัดดังกล่าว โปรดตรวจสอบว่าแอปพลิเคชันมีการขึ้นต่อกันกับไลบรารีการถอดรหัส
  • หากเห็นบันทึกระดับคำเตือนจาก LibraryLoader ใน Logcat แสดงว่าการโหลดคอมโพเนนต์เนทีฟของไลบรารีล้มเหลว หากเกิดกรณีนี้ขึ้น ให้ตรวจสอบว่าคุณได้ทำตามขั้นตอนใน README ของไลบรารีอย่างถูกต้องและไม่มีข้อผิดพลาดปรากฏขึ้นขณะทำตามคำแนะนำ

หากยังพบปัญหาในการใช้ไลบรารีการถอดรหัส โปรดตรวจสอบ เครื่องมือติดตามปัญหา Media3 เพื่อดูปัญหาล่าสุดที่เกี่ยวข้อง หากคุณต้องรายงานปัญหาใหม่และปัญหาดังกล่าวเกี่ยวข้องกับการสร้างส่วนเนทีฟของไลบรารี โปรดระบุเอาต์พุตบรรทัดคำสั่งทั้งหมดจากการทำตามคำแนะนำใน README เพื่อช่วยเราวินิจฉัยปัญหา

ฉันเล่นวิดีโอ YouTube ด้วย ExoPlayer ได้โดยตรงไหม

ไม่ได้ ExoPlayer เล่นวิดีโอจาก YouTube ไม่ได้ เช่น URL ในรูปแบบ https://www.youtube.com/watch?v=... คุณควรใช้ YouTube iFrame Player API, ซึ่งเป็นวิธีอย่างเป็นทางการในการเล่นวิดีโอ YouTube ใน Android

การเล่นวิดีโอติดขัด

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

หากวิดีโอติดขัดในอุปกรณ์ที่ใช้ Android เวอร์ชันตั้งแต่ Android 6.0 (ระดับ API 23) ถึง Android 11 (ระดับ API 30) โดยเฉพาะอย่างยิ่งเมื่อเล่นเนื้อหาที่ได้รับการปกป้องด้วย DRM หรือเนื้อหาที่มีอัตราเฟรมสูง คุณสามารถลองเปิดใช้การจัดคิวบัฟเฟอร์แบบไม่พร้อมกัน

ข้อผิดพลาด Lint ของ API ที่ไม่เสถียร

Media3 รับประกันความเข้ากันได้แบบไบนารีสำหรับชุดย่อยของพื้นผิว API ส่วนที่ ไม่ รับประกันความเข้ากันได้แบบไบนารีจะมีเครื่องหมาย @UnstableApi เพื่อให้เห็นความแตกต่างนี้อย่างชัดเจน การใช้สัญลักษณ์ API ที่ไม่เสถียรจะสร้างข้อผิดพลาด Lint เว้นแต่จะมีการใส่คำอธิบายประกอบด้วย @OptIn

คำอธิบายประกอบ @UnstableApi ไม่ได้บ่งบอกถึงคุณภาพหรือประสิทธิภาพของ API แต่บ่งบอกเพียงว่า API นั้น "ไม่ได้ถูกตรึงไว้"

คุณมี 2 ตัวเลือกในการจัดการข้อผิดพลาด Lint ของ API ที่ไม่เสถียร

  • เปลี่ยนไปใช้ API ที่เสถียรซึ่งให้ผลลัพธ์เหมือนกัน
  • ใช้ API ที่ไม่เสถียรต่อไปและใส่คำอธิบายประกอบการใช้งานด้วย @OptIn ดังที่แสดงไว้ในภายหลัง
เพิ่มคำอธิบายประกอบ @OptIn

Android Studio ช่วยคุณเพิ่มคำอธิบายประกอบได้

ภาพหน้าจอ: วิธีเพิ่มคำอธิบายประกอบการเลือกใช้
รูปที่ 2: การเพิ่มคำอธิบายประกอบ @androidx.annotations.OptIn ด้วย Android Studio

นอกจากนี้ คุณยังใส่คำอธิบายประกอบไซต์การใช้งานที่เฉพาะเจาะจงด้วยตนเองได้ด้วย

Kotlin

import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi

@OptIn(UnstableApi::class)
fun functionUsingUnstableApi() { ... }

Java

import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;

@OptIn(markerClass = UnstableApi.class)
private void methodUsingUnstableApis() { ... }

คุณเลือกใช้แพ็กเกจทั้งหมดได้โดยเพิ่มไฟล์ package-info

Kotlin

// In your package-info.kt
@OptIn(UnstableApi::class)
package name.of.your.package

import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi

Java

// In your package-info.java
@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;

import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;

คุณเลือกใช้โปรเจ็กต์ทั้งหมดได้โดยระงับข้อผิดพลาด Lint ที่เฉพาะเจาะจงในไฟล์ lint.xmlของโปรเจ็กต์:

 <?xml version="1.0" encoding="utf-8"?>
 <lint>
   <issue id="UnsafeOptInUsageError">
     <option name="opt-in" value="androidx.media3.common.util.UnstableApi" />
   </issue>
 </lint>

นอกจากนี้ยังมีคำอธิบายประกอบ kotlin.OptIn ซึ่งไม่ควรใช้ คุณต้องใช้คำอธิบายประกอบ androidx.annotation.OptIn