androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
Apache License 2.0
1.37k stars 324 forks source link

Media3 Transformer: Support `mediaStoreOutputOptions ` when calling `transformer.start()` #504

Open calren opened 1 year ago

calren commented 1 year ago

When working with Media3 Transformer, a transformation on a video is started by transformer.start(editedMediaItem, outputPath), but it would be more convenient if transformer.start() was also able to take in MediaStoreOutputOptions instead of a String outputPath.

This would be similar to how CameraX starts video recordings (https://developer.android.com/training/camerax/video-capture#configure-and-create-recording):

// Create MediaStoreOutputOptions for our recorder
val name = "CameraX-recording-" +
        SimpleDateFormat(FILENAME_FORMAT, Locale.US)
                .format(System.currentTimeMillis()) + ".mp4"
val contentValues = ContentValues().apply {
   put(MediaStore.Video.Media.DISPLAY_NAME, name)
}
val mediaStoreOutput = MediaStoreOutputOptions.Builder(this.contentResolver,
                              MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
                              .setContentValues(contentValues)
                              .build()

// 2. Configure Recorder and Start recording to the mediaStoreOutput.
val recording = videoCapture.output
                .prepareRecording(context, mediaStoreOutput)
                .withAudioEnabled()
                .start(ContextCompat.getMainExecutor(this), captureListener)

If this request is not prioritized, it would be useful to know what the best way is to work with a filepath and MediaStoreOutput. As in, how can the app take the file path and feed that into MediaStore so that the newly created file is also stored with the other media items of the app?

andrewlewis commented 1 year ago

Thanks for the request. We will look into it. For the current implementation, we are writing data using MediaMuxer which means it will be necessary to map onto a path or file descriptor eventually (used here).

hassanabidpk commented 1 week ago

Is there any update about this request? I set outfile path to that of Download directory instead of cache. Its not getting saved for me in latest 1.3.1 version

....
outputFile = createExternalDirectoryFile("transformer-output-" + Clock.DEFAULT.elapsedRealtime() + ".mp4")
private fun createExternalDirectoryFile(fileName: String): File {
        val downloadsDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
        val file = File(downloadsDirectory, fileName)
        check(!(file.exists() && !file.delete())) { "Could not delete the previous export output file" }
        check(file.createNewFile()) { "Could not create the export output file" }
        return file
    }

Do I need to get storage permissions ?

calren commented 1 week ago

Yes, you need storage permissions to save the output file. But that would also be the case even if MediaStoreOutputOptions was used instead.

Was this working for you before the 1.3.1 version?

hassanabidpk commented 1 week ago

Yes, you need storage permissions to save the output file. But that would also be the case even if MediaStoreOutputOptions was used instead.

Was this working for you before the 1.3.1 version?

I updated my code base yesterday to bump version to 1.3.1 (touching it after few months). Output is never saved in Downloads directory now. Previously in Dec 2023, I was able to save. Let me also double check my code as with storage permissions it was giving me permission denied error https://github.com/hassanabidpk/Media3Sample/blob/devfest-2023/app/src/main/java/com/hassan/media3sample/TransformerActivity.kt I was using it to demo at Devfest 2023 events.

hassanabidpk commented 1 week ago
calren commented 1 week ago

Thanks for testing and reporting back, I'll see if I can reproduce.