미디어 항목에 관한 자세한 내용은 ExoPlayer 미디어 항목 페이지를 참고하세요. 입력은 프로그레시브 스트림 또는 적응형 스트림일 수 있지만 출력은 항상 프로그레시브 스트림입니다. 적응형 입력의 경우 변환을 위해 항상 최고 해상도 트랙이 선택됩니다. 입력은 ExoPlayer에서 지원하는 모든 컨테이너 형식일 수 있지만 출력은 항상 MP4 파일입니다.
동일한 Transformer 인스턴스에서 여러 내보내기 작업을 순차적으로 실행할 수 있지만 동일한 인스턴스를 사용한 동시 내보내기는 지원되지 않습니다.
스레딩 관련 참고사항
트랜스포머 인스턴스는 단일 애플리케이션 스레드에서 액세스해야 하며 리스너 메서드는 동일한 스레드에서 호출됩니다. 대부분의 경우 애플리케이션 스레드는 애플리케이션의 기본 스레드일 수 있습니다. 내부적으로 트랜스포머는 백그라운드에서 작업을 실행하고 애플리케이션 스레드에서 리스너 메서드에 대한 호출을 게시합니다.
이벤트 수신 대기
start 메서드는 비동기적입니다. 즉시 반환되며 앱은 Transformer 빌더에 전달된 리스너를 통해 이벤트 알림을 받습니다.
ExportResult에는 파일 크기, 오디오 및 동영상의 평균 비트 전송률(해당하는 경우) 등 출력 파일에 관한 정보가 포함됩니다.
진행 상황 업데이트 받기
Transformer.getProgress를 호출하여 변환의 현재 진행 상황을 쿼리합니다. 반환된 값은 진행 상태를 나타냅니다. 진행 상태가 PROGRESS_STATE_AVAILABLE이면 제공된 ProgressHolder이 현재 진행률로 업데이트됩니다. 다음 예에서는 변환 진행률을 주기적으로 쿼리하는 방법을 보여줍니다. 여기서 updateProgressInUi 메서드를 구현하여 진행률 표시줄을 업데이트할 수 있습니다.
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-08-27(UTC)"],[],[],null,["Getting started with `Transformer` consists of the following steps:\n\n1. Add Media3 Transformer as a dependency in your project.\n2. Build an `EditedMediaItem` representing the media to process and edits to apply to it.\n3. Build a `Transformer`, describing the required output and a listener for completion and error events.\n4. Start the export operation, passing in the `EditedMediaItem` to edit and an output path. During export, you can query the current progress or cancel the operation.\n5. When exporting finishes, handle the output as needed. For example, you can share the output to another app or upload it to a server.\n\nRead on for more detail about these steps, and see `TransformerActivity` in the\n[transformer demo\napp](https://github.com/androidx/media/tree/release/demos/transformer) for a\ncomplete example.\n\nAdd Media3 Transformer as a dependency\n\nThe easiest way to get started using Transformer is to add gradle dependencies\non the library in the `build.gradle` file of your app module: \n\nKotlin \n\n```kotlin\nimplementation(\"androidx.media3:media3-transformer:1.8.0\")\nimplementation(\"androidx.media3:media3-effect:1.8.0\")\nimplementation(\"androidx.media3:media3-common:1.8.0\")\n```\n\nGroovy \n\n```groovy\nimplementation \"androidx.media3:media3-transformer:1.8.0\"\nimplementation \"androidx.media3:media3-effect:1.8.0\"\nimplementation \"androidx.media3:media3-common:1.8.0\"\n```\n\nwhere 1.8.0 is your preferred version. The latest version can be\nfound by consulting the [release\nnotes](https://github.com/androidx/media/tree/release/RELEASENOTES.md).\n| **Important:** If you're using any other Media3 modules, including Media3 ExoPlayer, they must all be the same version.\n\nMore information on the library modules that are available can be found on the\n[Google Maven AndroidX Media3\npage](https://maven.google.com/web/index.html?q=media3).\n\nTurn on Java 8 support\n\nIf not enabled already, you need to turn on Java 8 support in all `build.gradle`\nfiles that depend on Transformer by adding the following to the `android`\nsection: \n\n compileOptions {\n targetCompatibility JavaVersion.VERSION_1_8\n }\n\nStart a transformation\n\nHere's an example of creating an `EditedMediaItem` to remove audio for an input\nfile, then creating and configuring a `Transformer` instance to export\nH.265/HEVC video, outputting the result to `outputPath`. \n\nKotlin \n\n```kotlin\nval inputMediaItem = MediaItem.fromUri(\"path_to_input_file\")\nval editedMediaItem =\n EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build()\nval transformer = Transformer.Builder(context)\n .setVideoMimeType(MimeTypes.VIDEO_H265)\n .addListener(transformerListener)\n .build()\ntransformer.start(editedMediaItem, outputPath)\n```\n\nJava \n\n```java\nMediaItem inputMediaItem = MediaItem.fromUri(\"path_to_input_file\");\nEditedMediaItem editedMediaItem =\n new EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(true).build();\nTransformer transformer =\n new Transformer.Builder(context)\n .setVideoMimeType(MimeTypes.VIDEO_H265)\n .addListener(transformerListener)\n .build();\ntransformer.start(editedMediaItem, outputPath);\n```\n\n\u003cbr /\u003e\n\nFor more information about media items, see the [ExoPlayer media items\npage](../exoplayer/media-items). The input can be a progressive or an adaptive\nstream, but the output is always a progressive stream. For adaptive inputs, the\nhighest-resolution tracks are always selected for the transformation. The input\ncan be of any container format [supported](/media/media3/transformer/supported-formats) by ExoPlayer, but\nthe output is always an MP4 file.\n\nYou can execute multiple export operations sequentially on the same\n`Transformer` instance, but concurrent exports with the same instance are not\nsupported.\n| **Note:** Support for generating media by composing together multiple inputs is planned for future versions of Transformer.\n\nA note on threading\n\nTransformer instances must be accessed from a single application thread, and the\nlistener methods are called on the same thread. For the majority of cases, the\napplication thread can just be the main thread of the application. Internally,\nTransformer does its work in the background and posts its calls to listener\nmethods on the application thread.\n\nListen to events\n\nThe `start` method is asynchronous. It returns immediately and the app is\nnotified of events through the listener passed to the `Transformer` builder. \n\nKotlin \n\n```kotlin\nval transformerListener: Transformer.Listener =\n object : Transformer.Listener {\n override fun onCompleted(composition: Composition, result: ExportResult) {\n playOutput()\n }\n\n override fun onError(composition: Composition, result: ExportResult,\n exception: ExportException) {\n displayError(exception)\n }\n}\n```\n\nJava \n\n```java\nTransformer.Listener transformerListener =\n new Transformer.Listener() {\n @Override\n public void onCompleted(Composition composition, ExportResult result) {\n playOutput();\n }\n\n @Override\n public void onError(Composition composition, ExportResult result,\n ExportException exception) {\n displayError(exception);\n }\n };\n```\n\n\u003cbr /\u003e\n\n`ExportResult` includes information about the output file, including the file\nsize and average bitrates for audio and video, as applicable.\n\nGet progress updates\n\nCall `Transformer.getProgress` to query the current progress of a\ntransformation. The returned value indicates the progress state. If the progress\nstate is `PROGRESS_STATE_AVAILABLE`, then the provided `ProgressHolder` is\nupdated with the current progress percentage. The following example shows how to\nperiodically query the progress of a transformation, where the\n`updateProgressInUi` method can be implemented to update a progress bar. \n\nKotlin \n\n```kotlin\ntransformer.start(inputMediaItem, outputPath)\nval progressHolder = ProgressHolder()\nmainHandler.post(\n object : Runnable {\n override fun run() {\n val progressState: @ProgressState Int = transformer.getProgress(progressHolder)\n updateProgressInUi(progressState, progressHolder)\n if (progressState != Transformer.PROGRESS_STATE_NOT_STARTED) {\n mainHandler.postDelayed(/* r= */this, /* delayMillis= */500)\n }\n }\n }\n)\n```\n\nJava \n\n```java\ntransformer.start(inputMediaItem, outputPath);\nProgressHolder progressHolder = new ProgressHolder();\nmainHandler.post(\n new Runnable() {\n @Override\n public void run() {\n @Transformer.ProgressState int progressState = transformer.getProgress(progressHolder);\n updateProgressInUi(progressState, progressHolder);\n if (progressState != PROGRESS_STATE_NOT_STARTED) {\n mainHandler.postDelayed(/* r= */ this, /* delayMillis= */ 500);\n }\n }\n });\n```\n\n\u003cbr /\u003e\n\nCancel a transformation\n\nIf the user chooses to back out of an export flow, cancel the export operation\nwith `Transformer.cancel`. Resources like hardware video codecs are limited,\nespecially on lower-end devices, so it's important to do this to free up\nresources if the output isn't needed."]]