Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple video sequences in CompositionPlayer #1488

Open
pawaom opened this issue Jun 23, 2024 · 2 comments
Open

Support multiple video sequences in CompositionPlayer #1488

pawaom opened this issue Jun 23, 2024 · 2 comments
Assignees
Labels
editing enhancement preview CompositionPlayer issues

Comments

@pawaom
Copy link

pawaom commented Jun 23, 2024

Preview composition crashes with EditedMediaItem.getPresentationDurationUs error using media3_version = "1.4.0-alpha02"

I am trying this code to create a PIP video effect

private LinearProgressIndicator progressIndicator;
    ViewGroup progressViewGroup;
    private AspectRatioFrameLayout debugaspectRatioFrameLayout;
    Uri VideoUri2, VideoUri;
    TextView Video2TextView, VideoTextView;
    Button VideoButton, Video2Button, TransformButton;
    ActivityResultLauncher<String> VideoGetContent = registerForActivityResult(new ActivityResultContracts.GetContent(),
            new ActivityResultCallback<Uri>() {
                @Override
                public void onActivityResult(Uri uri) {
                    // Handle the returned Uri
                    VideoUri = uri;
                    VideoTextView.setText(VideoUri.toString());
                    MediaItem inputMediaItem = new MediaItem.Builder().setUri(VideoUri).build();
                    //  cropEffect(inputMediaItem);
                }
            });

    ActivityResultLauncher<String> AudioGetContent = registerForActivityResult(new ActivityResultContracts.GetContent(),
            uri -> {
                // Handle the returned Uri
                VideoUri2 = uri;
                Video2TextView.setText(VideoUri2.toString());
            });
    private Handler mainHandler;
    private String outputPath;
    CompositionPlayer outputPlayer;
    PlayerView outputPlayerView;

    @OptIn(markerClass = UnstableApi.class)
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.exxoplayerviewtry);

        //   progressViewGroup = findViewById(R.id.progress_view_group1);
        progressIndicator = findViewById(R.id.progress_indicator);
        VideoTextView = findViewById(R.id.textView);
        this.outputPlayerView = findViewById(R.id.output_player_view);

        Video2TextView = findViewById(R.id.textView2);
        VideoButton = findViewById(R.id.button);
        debugaspectRatioFrameLayout = findViewById(R.id.debug_aspect_ratio_frame_layout);

        VideoButton.setOnClickListener(view -> {
            // Pass in the mime type you want to let the user select
            // as the input
            VideoGetContent.launch("video/*");
        });

        Video2Button = findViewById(R.id.button2);

        Video2Button.setOnClickListener(view -> {
            // Pass in the mime type you want to let the user select
            // as the input
            AudioGetContent.launch("video/*");
        });

        TransformButton = findViewById(R.id.button3);

        TransformButton.setOnClickListener(view -> {
            // Pass in the mime type you want to let the user select
            // as the input
           // createTransform();
            PreviewComposition();
        });
    }

    public void createTransform() {
        Transformer transformer =
                new Transformer.Builder(this)
                        .setTransformationRequest(
                                new TransformationRequest.Builder().build())
                        .addListener(transformerListener)

                        .build();
        try {
            outputPath = createOutputFile().getAbsolutePath();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        transformer.start(myComposition(), outputPath);
        ProgressHolder progressHolder = new ProgressHolder();
        mainHandler = new Handler(Looper.getMainLooper());
        mainHandler.post(
                new Runnable() {
                    @Override
                    public void run() {
                        if (transformer != null
                                && transformer.getProgress(progressHolder) != PROGRESS_STATE_NOT_STARTED) {
                            progressIndicator.setProgress(progressHolder.progress);
                            mainHandler.postDelayed(/* r= */ this, /* delayMillis= */ 500);
                        }
                    }
                });
    }

    @UnstableApi
    Transformer.Listener transformerListener =
            new Transformer.Listener() {
                @Override
                public void onCompleted(Composition composition, ExportResult result) {
                    // playOutput();
                    Toast.makeText(ExoPlayerTry.this, "Done ", Toast.LENGTH_LONG).show();
                }

                @Override
                public void onError(Composition composition, ExportResult result,
                                    ExportException exception) {
                    // displayError(exception);
                    Toast.makeText(ExoPlayerTry.this, "" + exception.toString(), Toast.LENGTH_SHORT).show();
                    Log.e("TAG", "Export error", exception);
                }
            };

    private File createOutputFile() throws IOException {
        String videoFileName = "video_" + System.currentTimeMillis() + ".mp4";
        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), videoFileName);
        if (file.exists() && !file.delete()) {
            throw new IllegalStateException("Could not delete the previous export output file");
        }
        if (!file.createNewFile()) {
            throw new IllegalStateException("Could not create the export output file");
        }
        return file;
    }

    private void releasePlayer() {
        if (outputPlayer != null) {
            outputPlayer.release();
            outputPlayer = null;
        }
    }

    public void PreviewComposition() {
        releasePlayer();
        this.outputPlayerView.setPlayer(null);
        //Composition composition = createoOwnComposition();
        Composition composition = myComposition();
        CompositionPlayer player = new CompositionPlayer.Builder(getApplicationContext()).build();
        this.outputPlayer = player;
        this.outputPlayerView.setPlayer(outputPlayer);
        this.outputPlayerView.setControllerAutoShow(false);
        player.setComposition(composition);
        player.addListener(
                new Player.Listener() {
                    @Override
                    public void onPlayerError(PlaybackException error) {
                        Toast.makeText(getApplicationContext(), "Preview error: " + error, Toast.LENGTH_LONG)
                                .show();
                        Log.e("TAG", "Preview error", error);
                    }
                });

        player.prepare();
        player.play();
    }

    VideoCompositorSettings pictureInPictureVideoCompositorSettings =
            new VideoCompositorSettings() {
                @Override
                public Size getOutputSize(List<Size> inputSizes) {
                    return inputSizes.get(0);
                }

                @Override
                public OverlaySettings getOverlaySettings(int inputId, long presentationTimeUs) {
                    if (inputId == 0) {
                        // This tests all OverlaySettings builder variables.
                        return new OverlaySettings.Builder()
                                .setScale(.25f, .25f)
                                .setOverlayFrameAnchor(1, -1)
                                .setBackgroundFrameAnchor(.9f, -.7f)
                                .build();
                    } else {
                        return new OverlaySettings.Builder().build();
                    }
                }
            };

    private static final long ONE_FRAME_DURATION_MS = 35;

    private static EditedMediaItem editedMediaItemByClippingVideo(String uri, List<Effect> effects) {
        return new EditedMediaItem.Builder(
                MediaItem.fromUri(uri)
                        .buildUpon()
                        .setClippingConfiguration(
                                new MediaItem.ClippingConfiguration.Builder()
                                        .setEndPositionMs(ONE_FRAME_DURATION_MS)
                                        .build())
                        .build())
                .setRemoveAudio(true)
                .setEffects(
                        new Effects(/* audioProcessors= */ ImmutableList.of(), ImmutableList.copyOf(effects))).setDurationUs(1000)
                .build();
    }

    private static Composition createComposition(
            List<Effect> compositionEffects,
            List<EditedMediaItem> firstSequenceMediaItems,
            List<EditedMediaItem> secondSequenceMediaItems,
            VideoCompositorSettings videoCompositorSettings) {

        return new Composition.Builder(
                ImmutableList.of(
                        new EditedMediaItemSequence(firstSequenceMediaItems),
                        new EditedMediaItemSequence(secondSequenceMediaItems)))
                .setEffects(
                        new Effects(
                                /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ compositionEffects))
                .setVideoCompositorSettings(videoCompositorSettings)
                .build();
    }

    public Composition myComposition() {
        Composition composition =
                createComposition(
                        /* compositionEffects= */ ImmutableList.of(
                                new Contrast(0.1f),
                                Presentation.createForWidthAndHeight(
                                        500, 500, Presentation.LAYOUT_SCALE_TO_FIT)),
                        /* firstSequenceMediaItems= */ ImmutableList.of(
                                editedMediaItemByClippingVideo(
                                        String.valueOf(VideoUri),
                                        /* effects= */ ImmutableList.of(
                                                new AlphaScale(0.5f),
                                                new ScaleAndRotateTransformation.Builder()
                                                        .setRotationDegrees(180)
                                                        .build()))),
                        /* secondSequenceMediaItems= */ ImmutableList.of(
                                editedMediaItemByClippingVideo(
                                        String.valueOf(VideoUri2), /* effects= */ ImmutableList.of())),
                        pictureInPictureVideoCompositorSettings);

        return composition;
    }

This is the Preview composition method

 public void PreviewComposition() {
        releasePlayer();
        this.outputPlayerView.setPlayer(null);
        //Composition composition = createoOwnComposition();
        Composition composition = myComposition();
        CompositionPlayer player = new CompositionPlayer.Builder(getApplicationContext()).build();
        this.outputPlayer = player;
        this.outputPlayerView.setPlayer(outputPlayer);
        this.outputPlayerView.setControllerAutoShow(false);
        player.setComposition(composition);
        player.addListener(
                new Player.Listener() {
                    @Override
                    public void onPlayerError(PlaybackException error) {
                        Toast.makeText(getApplicationContext(), "Preview error: " + error, Toast.LENGTH_LONG)
                                .show();
                        Log.e("TAG", "Preview error", error);
                    }
                });

        player.prepare();
        player.play();
    }


and the my composition method

public Composition myComposition() {
        Composition composition =
                createComposition(
                        /* compositionEffects= */ ImmutableList.of(
                                new Contrast(0.1f),
                                Presentation.createForWidthAndHeight(
                                        500, 500, Presentation.LAYOUT_SCALE_TO_FIT)),
                        /* firstSequenceMediaItems= */ ImmutableList.of(
                                editedMediaItemByClippingVideo(
                                        String.valueOf(VideoUri),
                                        /* effects= */ ImmutableList.of(
                                                new AlphaScale(0.5f),
                                                new ScaleAndRotateTransformation.Builder()
                                                        .setRotationDegrees(180)
                                                        .build()))),
                        /* secondSequenceMediaItems= */ ImmutableList.of(
                                editedMediaItemByClippingVideo(
                                        String.valueOf(VideoUri2), /* effects= */ ImmutableList.of())),
                        pictureInPictureVideoCompositorSettings);

        return composition;
    }
 

when I try to create a video using Transformer it creates the video however When I try to preview the composition I get the following error

 FATAL EXCEPTION: main (Ask Gemini)
  Process: org.own.media14beta, PID: 20379
 java.lang.IllegalArgumentException
  at androidx.media3.common.util.Assertions.checkArgument(Assertions.java:40)
   at androidx.media3.transformer.EditedMediaItem.getPresentationDurationUs(EditedMediaItem.java:297)
   at androidx.media3.transformer.CompositionPlayer.getSequenceDurationUs(CompositionPlayer.java:809)
   at androidx.media3.transformer.CompositionPlayer.getCompositionDurationUs(CompositionPlayer.java:792)
   at androidx.media3.transformer.CompositionPlayer.setCompositionInternal(CompositionPlayer.java:586)
   at androidx.media3.transformer.CompositionPlayer.setComposition(CompositionPlayer.java:321)
   at org.own.media14beta.ExoPlayerTry.PreviewComposition(ExoPlayerTry.java:218)
   at org.own.media14beta.ExoPlayerTry.lambda$onCreate$3$org-own-media14beta-ExoPlayerTry(ExoPlayerTry.java:138)
   at org.own.media14beta.ExoPlayerTry$$ExternalSyntheticLambda3.onClick(D8$$SyntheticClass:0)
   at android.view.View.performClick(View.java:8043)
   at android.widget.TextView.performClick(TextView.java:17817)
   at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1218)
   at android.view.View.performClickInternal(View.java:8020)
   at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
   at android.view.View$PerformClick.run(View.java:31867)
   at android.os.Handler.handleCallback(Handler.java:958)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loopOnce(Looper.java:230)
   at android.os.Looper.loop(Looper.java:319)
   at android.app.ActivityThread.main(ActivityThread.java:8913)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)

@droid-girl
Copy link
Contributor

droid-girl commented Jun 23, 2024

Hi @pawaom ,
Please keep in mind that CompositionPlayer is still under active development and work-in-progress and @RestrictTo to indicate that this API should not be used outside of the library.
This type of Composition that you are trying to build is not supported at the moment and this is the reason you are not able to preview your Composition. CompositionPlayer only supports single video input at the moment.
Please keep an eye on future releases for any announcements.

@pawaom
Copy link
Author

pawaom commented Jun 24, 2024

can this be tagged as enhancement so that we can track the development

@droid-girl droid-girl reopened this Jun 25, 2024
@droid-girl droid-girl added the preview CompositionPlayer issues label Jun 25, 2024
@droid-girl droid-girl changed the title Preview composition crashes with EditedMediaItem.getPresentationDurationUs error Support multiple video sequences in CompositionPlayer Jul 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
editing enhancement preview CompositionPlayer issues
Projects
None yet
Development

No branches or pull requests

2 participants