การเปลี่ยนรูปแบบ

Jetpack Media3 Transformer ช่วยให้คุณแก้ไข แปลง และส่งออกชิ้นงานสื่อ บน Android ได้ หน้านี้อธิบายวิธีกำหนดค่าการแปลงหลัก

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

แปลงรหัสระหว่างรูปแบบ

คุณสามารถระบุรูปแบบเสียงและวิดีโอเอาต์พุตที่ต้องการสร้างเมื่อสร้าง Transformer ตัวอย่างเช่น โค้ดต่อไปนี้แสดงวิธีกำหนดค่า Transformer เพื่อเอาต์พุตวิดีโอ H.264/AVC และเสียง AAC

Kotlin

Transformer.Builder(context)
  .setVideoMimeType(MimeTypes.VIDEO_H264)
  .setAudioMimeType(MimeTypes.AUDIO_AAC)
  .build()

Java

new Transformer.Builder(context)
    .setVideoMimeType(MimeTypes.VIDEO_H264)
    .setAudioMimeType(MimeTypes.AUDIO_AAC)
    .build();

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

นำเสียงหรือวิดีโอออก

นำเสียงหรือวิดีโอออกโดยใช้ EditedMediaItem.Builder เช่น

Kotlin

EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()

Java

new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();

ตัดคลิป

คุณสามารถนำสื่อใดๆ ที่อยู่นอกการประทับเวลาเริ่มต้นและสิ้นสุดที่ระบุออกได้โดยการตั้งค่าการตัดในรายการสื่ออินพุต ตัวอย่างเช่น หากต้องการสร้างคลิปที่มีเฉพาะสื่อระหว่าง 10 วินาทีถึง 20 วินาที ให้ทำดังนี้

Kotlin

val inputMediaItem =
  MediaItem.Builder()
    .setUri(uri)
    .setClippingConfiguration(
      MediaItem.ClippingConfiguration.Builder()
        .setStartPositionMs(10_000)
        .setEndPositionMs(20_000)
        .build()
    )
    .build()

Java

MediaItem inputMediaItem =
    new MediaItem.Builder()
        .setUri(uri)
        .setClippingConfiguration(
            new MediaItem.ClippingConfiguration.Builder()
                .setStartPositionMs(10_000)
                .setEndPositionMs(20_000)
                .build())
        .build();

รายการแก้ไข MP4

Transformer รองรับรายการแก้ไข MP4 เพื่อการตัดที่เร็วขึ้น ซึ่งช่วยให้แก้ไข "การตัดเท่านั้น" ได้อย่างมีประสิทธิภาพมากขึ้นโดยไม่ต้องแปลงรหัสวิดีโอทั้งหมดใหม่ วิธีนี้ใช้ตัวอย่างที่เข้ารหัสที่มีอยู่และ "โฆษณาตอนต้น" ภายในรายการแก้ไข ซึ่งจะสั่งให้เพลเยอร์เริ่มเล่นที่จุดหนึ่งโดยเฉพาะ ซึ่งเป็นการข้ามส่วนเริ่มต้นที่ไม่ต้องการได้อย่างมีประสิทธิภาพ

หากต้องการให้การแก้ไขแบบตัดเท่านั้นเร็วขึ้นอย่างมาก ให้เรียกใช้ experimentalSetMp4EditListTrimEnabled(true)

Kotlin

Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build()

Java

new Transformer.Builder(context).experimentalSetMp4EditListTrimEnabled(true).build();
โปรดทราบว่าเครื่องเล่นสื่อบางเครื่องไม่รองรับตำแหน่ง "โฆษณาก่อนเล่น" ซึ่งหมายความว่าเมื่อใช้เครื่องเล่นดังกล่าว ไฟล์จะเริ่มเล่นจากจุดเริ่มต้นของตัวอย่างที่เข้ารหัส ไม่ว่าข้อมูลรายการแก้ไขจะระบุจุดเริ่มต้นอื่นก็ตาม

การเพิ่มประสิทธิภาพการตัด

หากต้องการลดเวลาในการตอบสนองของการตัดวิดีโอส่วนต้น ให้เปิดใช้การเพิ่มประสิทธิภาพการตัด

Kotlin

Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build()

Java

new Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build();

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

การเพิ่มประสิทธิภาพนี้ใช้ได้กับอินพุต MP4 แบบชิ้นงานเดียวที่ไม่มีเอฟเฟกต์ใดๆ ยกเว้นเอฟเฟกต์วิดีโอแบบไม่มีการดำเนินการและเอฟเฟกต์การหมุนที่หารด้วย 90 องศาลงตัว หากการเพิ่มประสิทธิภาพล้มเหลว Transformer จะกลับไปใช้การส่งออกปกติโดยอัตโนมัติ และรายงานผลลัพธ์ของการเพิ่มประสิทธิภาพใน ExportResult.OptimizationResult

เรากำลังตรวจสอบฟังก์ชันการทำงานนี้และคาดว่าจะไม่ใช่ฟังก์ชันการทำงานแบบทดลองในรุ่นต่อๆ ไป

การแก้ไขวิดีโอ

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

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

Kotlin

EditedMediaItem.Builder(MediaItem.fromUri(uri))
  .setEffects(
    Effects(
      /* audioProcessors= */ listOf(),
      /* videoEffects= */ listOf(Presentation.createForHeight(480)),
    )
  )
  .build()

Java

new EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(
        new Effects(
            /* audioProcessors= */ ImmutableList.of(),
            /* videoEffects= */ ImmutableList.of(Presentation.createForHeight(480))))
    .build();

หรือคุณจะปรับขนาดตามปัจจัยที่กำหนดก็ได้ เช่น หากต้องการลดขนาดลงครึ่งหนึ่ง ให้ทำดังนี้

Kotlin

val editedMediaItem =
  EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(
      Effects(
        /* audioProcessors= */ listOf(),
        /* videoEffects= */ listOf(
          ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build()
        ),
      )
    )
    .build()

Java

new EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(
        new Effects(
            /* audioProcessors= */ ImmutableList.of(),
            /* videoEffects= */ ImmutableList.of(
                new ScaleAndRotateTransformation.Builder().setScale(.5f, .5f).build())))
    .build();

คุณสามารถกำหนดค่าการหมุนได้ด้วยวิธีเดียวกัน

Kotlin

EditedMediaItem.Builder(MediaItem.fromUri(uri))
  .setEffects(
    Effects(
      /* audioProcessors= */ listOf(),
      /* videoEffects= */ listOf(
        ScaleAndRotateTransformation.Builder().setRotationDegrees(90f).build()
      ),
    )
  )
  .build()

Java

new EditedMediaItem.Builder(MediaItem.fromUri(uri))
    .setEffects(
        new Effects(
            /* audioProcessors= */ ImmutableList.of(),
            /* videoEffects= */ ImmutableList.of(
                new ScaleAndRotateTransformation.Builder().setRotationDegrees(90f).build())))
    .build();

เอฟเฟกต์วิดีโอที่กำหนดเอง

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

นอกจากนี้ ExoPlayer ยังรองรับเอฟเฟกต์วิดีโอสำหรับการดูตัวอย่างโดยใช้ ExoPlayer.setVideoEffects หากต้องการดูตัวอย่างวิธีใช้ API นี้ โปรดดู แอปเดโมเอฟเฟกต์

แอปเดโมมีตัวอย่างเอฟเฟกต์วิดีโอที่กำหนดเอง

อินพุตรูปภาพ

Transformer รองรับอินพุตรูปภาพโดยถือว่าเป็นวิดีโอคลิปแบบคงที่ หากต้องการกำหนดค่ารูปภาพเป็นแหล่งที่มาของอินพุต ให้ทำตามขั้นตอนต่อไปนี้

  • สร้าง MediaItem โดยใช้ MediaItem.Builder ระบุระยะเวลาการแสดงรูปภาพในวิดีโอเอาต์พุตโดยเรียกใช้ setImageDurationMs

  • สร้าง EditedMediaItem ที่ครอบ MediaItem ระบุอัตราเฟรมเป้าหมายสำหรับสตรีมวิดีโอที่สร้างขึ้นโดยใช้ EditedMediaItem.Builder#setFrameRate

ตัวอย่างต่อไปนี้แสดงวิธีกำหนดค่าอินพุตรูปภาพเพื่อสร้างวิดีโอ 5 วินาทีที่ 30 เฟรมต่อวินาที

Kotlin

val imageMediaItem =
  MediaItem.Builder()
    .setUri(imageUri)
    .setImageDurationMs(5000) // 5 seconds
    .build()

val editedImageItem =
  EditedMediaItem.Builder(imageMediaItem)
    .setFrameRate(30) // 30 frames per second
    .build()

Java

MediaItem imageMediaItem =
    new MediaItem.Builder()
        .setUri(imageUri)
        .setImageDurationMs(5000) // 5 seconds
        .build();
new EditedMediaItem.Builder(imageMediaItem)
    .setFrameRate(30) // 30 frames per second
    .build();

การแก้ไขเสียง

เอฟเฟกต์เสียงจะใช้งานโดยการใช้ลำดับอินสแตนซ์ AudioProcessor กับเสียงดิบ (PCM) ExoPlayer รองรับการส่งโปรเซสเซอร์เสียงไปยัง DefaultAudioSink.Builder ซึ่งช่วยให้ดูตัวอย่างการแก้ไขเสียงได้