mirror of
https://github.com/androidx/media.git
synced 2025-04-29 22:36:54 +08:00
Add setForceAudioTrack method on EditedMediaItemSequence
PiperOrigin-RevId: 740808813
This commit is contained in:
parent
0d60c5bf25
commit
87e0d7b95a
@ -22,7 +22,6 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.VideoCompositorSettings;
|
||||
import androidx.media3.common.audio.AudioProcessor;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
@ -121,40 +120,9 @@ public final class Composition {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the output file should always contain an audio track.
|
||||
*
|
||||
* <p>The default value is {@code false}.
|
||||
*
|
||||
* <ul>
|
||||
* <li>If {@code false}:
|
||||
* <ul>
|
||||
* <li>If the {@link Composition} export doesn't produce any audio at timestamp 0, but
|
||||
* produces audio later on, the export is {@linkplain
|
||||
* Transformer.Listener#onError(Composition, ExportResult, ExportException)
|
||||
* aborted}.
|
||||
* <li>If the {@link Composition} doesn't produce any audio during the entire export,
|
||||
* the output won't contain any audio.
|
||||
* <li>If the {@link Composition} export produces audio at timestamp 0, the output will
|
||||
* contain an audio track.
|
||||
* </ul>
|
||||
* <li>If {@code true}, the output will always contain an audio track.
|
||||
* </ul>
|
||||
*
|
||||
* If the output contains an audio track, silent audio will be generated for the segments where
|
||||
* the {@link Composition} export doesn't produce any audio.
|
||||
*
|
||||
* <p>The MIME type of the output's audio track can be set using {@link
|
||||
* Transformer.Builder#setAudioMimeType(String)}. The sample rate and channel count can be set
|
||||
* by passing relevant {@link AudioProcessor} instances to the {@link Composition}.
|
||||
*
|
||||
* <p>Forcing an audio track and {@linkplain #setTransmuxAudio(boolean) requesting audio
|
||||
* transmuxing} are not allowed together because generating silence requires transcoding.
|
||||
*
|
||||
* <p>This method is experimental and may be removed or changed without warning.
|
||||
*
|
||||
* @param forceAudioTrack Whether to force an audio track in the output.
|
||||
* @return This builder.
|
||||
* @deprecated Use {@link EditedMediaItemSequence.Builder#setForceAudioTrack(boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@CanIgnoreReturnValue
|
||||
public Builder experimentalSetForceAudioTrack(boolean forceAudioTrack) {
|
||||
this.forceAudioTrack = forceAudioTrack;
|
||||
@ -260,8 +228,20 @@ public final class Composition {
|
||||
|
||||
/** Builds a {@link Composition} instance. */
|
||||
public Composition build() {
|
||||
ImmutableList<EditedMediaItemSequence> updatedSequences;
|
||||
if (forceAudioTrack) {
|
||||
ImmutableList.Builder<EditedMediaItemSequence> updatedSequencesBuilder =
|
||||
new ImmutableList.Builder<>();
|
||||
for (int i = 0; i < sequences.size(); i++) {
|
||||
updatedSequencesBuilder.add(
|
||||
sequences.get(i).buildUpon().setForceAudioTrack(forceAudioTrack).build());
|
||||
}
|
||||
updatedSequences = updatedSequencesBuilder.build();
|
||||
} else {
|
||||
updatedSequences = sequences;
|
||||
}
|
||||
return new Composition(
|
||||
sequences,
|
||||
updatedSequences,
|
||||
videoCompositorSettings,
|
||||
effects,
|
||||
forceAudioTrack,
|
||||
@ -379,11 +359,10 @@ public final class Composition {
|
||||
public final Effects effects;
|
||||
|
||||
/**
|
||||
* Whether the output file should always contain an audio track.
|
||||
*
|
||||
* <p>For more information, see {@link Builder#experimentalSetForceAudioTrack(boolean)}.
|
||||
* @deprecated Use {@link EditedMediaItemSequence.Builder#setForceAudioTrack(boolean)} to set the
|
||||
* flag and {@link EditedMediaItemSequence#forceAudioTrack} to read the flag.
|
||||
*/
|
||||
public final boolean forceAudioTrack;
|
||||
@Deprecated public final boolean forceAudioTrack;
|
||||
|
||||
/**
|
||||
* Whether to transmux the {@linkplain MediaItem media items'} audio tracks.
|
||||
|
@ -18,6 +18,7 @@ package androidx.media3.transformer;
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.audio.AudioProcessor;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
@ -35,6 +36,7 @@ public final class EditedMediaItemSequence {
|
||||
public static final class Builder {
|
||||
private final ImmutableList.Builder<EditedMediaItem> items;
|
||||
private boolean isLooping;
|
||||
private boolean forceAudioTrack;
|
||||
|
||||
/** Creates an instance. */
|
||||
public Builder(EditedMediaItem... editedMediaItems) {
|
||||
@ -46,6 +48,15 @@ public final class EditedMediaItemSequence {
|
||||
items = new ImmutableList.Builder<EditedMediaItem>().addAll(editedMediaItems);
|
||||
}
|
||||
|
||||
/** Creates a new instance to build upon the provided {@link EditedMediaItemSequence}. */
|
||||
private Builder(EditedMediaItemSequence editedMediaItemSequence) {
|
||||
items =
|
||||
new ImmutableList.Builder<EditedMediaItem>()
|
||||
.addAll(editedMediaItemSequence.editedMediaItems);
|
||||
isLooping = editedMediaItemSequence.isLooping;
|
||||
forceAudioTrack = editedMediaItemSequence.forceAudioTrack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@linkplain EditedMediaItem item} to the sequence.
|
||||
*
|
||||
@ -116,6 +127,41 @@ public final class EditedMediaItemSequence {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces silent audio in the {@linkplain EditedMediaItemSequence sequence}.
|
||||
*
|
||||
* <p>This flag is necessary when:
|
||||
*
|
||||
* <ul>
|
||||
* <li>The first {@link EditedMediaItem} in the sequence does not contain audio, but
|
||||
* subsequent items do.
|
||||
* <li>The first item in the sequence is a {@linkplain #addGap(long) gap} and the subsequent
|
||||
* {@linkplain EditedMediaItem media items} contain audio.
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the flag is not set appropriately, then the export will {@linkplain
|
||||
* Transformer.Listener#onError(Composition, ExportResult, ExportException) fail}.
|
||||
*
|
||||
* <p>If the first {@link EditedMediaItem} already contains audio, this flag has no effect.
|
||||
*
|
||||
* <p>The MIME type of the output's audio track can be set using {@link
|
||||
* Transformer.Builder#setAudioMimeType(String)}. The sample rate and channel count can be set
|
||||
* by passing relevant {@link AudioProcessor} instances to the {@link Composition}.
|
||||
*
|
||||
* <p>Forcing an audio track and {@linkplain Composition.Builder#setTransmuxAudio(boolean)
|
||||
* requesting audio transmuxing} are not allowed together because generating silence requires
|
||||
* transcoding.
|
||||
*
|
||||
* <p>The default value is {@code false}.
|
||||
*
|
||||
* @param forceAudioTrack Whether to force audio track.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setForceAudioTrack(boolean forceAudioTrack) {
|
||||
this.forceAudioTrack = forceAudioTrack;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the {@link EditedMediaItemSequence}.
|
||||
*
|
||||
@ -147,6 +193,9 @@ public final class EditedMediaItemSequence {
|
||||
*/
|
||||
public final boolean isLooping;
|
||||
|
||||
/** Forces silent audio in the {@linkplain EditedMediaItemSequence sequence}. */
|
||||
public final boolean forceAudioTrack;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link Builder}.
|
||||
*/
|
||||
@ -172,11 +221,17 @@ public final class EditedMediaItemSequence {
|
||||
this(new Builder().addItems(editedMediaItems).setIsLooping(isLooping));
|
||||
}
|
||||
|
||||
/** Returns a {@link Builder} initialized with the values of this instance. */
|
||||
public Builder buildUpon() {
|
||||
return new Builder(this);
|
||||
}
|
||||
|
||||
private EditedMediaItemSequence(EditedMediaItemSequence.Builder builder) {
|
||||
this.editedMediaItems = builder.items.build();
|
||||
checkArgument(
|
||||
!editedMediaItems.isEmpty(), "The sequence must contain at least one EditedMediaItem.");
|
||||
this.isLooping = builder.isLooping;
|
||||
this.forceAudioTrack = builder.forceAudioTrack;
|
||||
}
|
||||
|
||||
/** Return whether any items are a {@linkplain Builder#addGap(long) gap}. */
|
||||
|
@ -68,7 +68,7 @@ public final class Effects {
|
||||
* <p>The {@linkplain AudioProcessor audio processor} and {@linkplain Effect video effect} are
|
||||
* interlinked to help maintain A/V sync. When using Transformer, if the input file doesn't have
|
||||
* audio, or audio is being removed, you may have to {@linkplain
|
||||
* Composition.Builder#experimentalSetForceAudioTrack force an audio track} for the interlinked
|
||||
* EditedMediaItemSequence.Builder#setForceAudioTrack force an audio track} for the interlinked
|
||||
* effects to function correctly. Alternatively, you can use {@link SpeedChangeEffect} when input
|
||||
* has no audio.
|
||||
*
|
||||
|
@ -130,7 +130,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
public SequenceAssetLoader(
|
||||
EditedMediaItemSequence sequence,
|
||||
boolean forceAudioTrack,
|
||||
Factory assetLoaderFactory,
|
||||
CompositionSettings compositionSettings,
|
||||
Listener listener,
|
||||
@ -138,7 +137,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
Looper looper) {
|
||||
editedMediaItems = sequence.editedMediaItems;
|
||||
isLooping = sequence.isLooping;
|
||||
this.forceAudioTrack = forceAudioTrack || sequence.editedMediaItems.get(0).isGap();
|
||||
this.forceAudioTrack = sequence.forceAudioTrack || sequence.editedMediaItems.get(0).isGap();
|
||||
this.assetLoaderFactory = new GapInterceptingAssetLoaderFactory(assetLoaderFactory);
|
||||
this.compositionSettings = compositionSettings;
|
||||
sequenceAssetLoaderListener = listener;
|
||||
|
@ -937,8 +937,8 @@ public final class Transformer {
|
||||
* <li>If an {@link EditedMediaItem} in a sequence contains data of a given {@linkplain
|
||||
* C.TrackType track}, so must all items in that sequence.
|
||||
* <ul>
|
||||
* <li>For audio, this condition can be removed by setting an experimental {@link
|
||||
* Composition.Builder#experimentalSetForceAudioTrack(boolean) flag}.
|
||||
* <li>For audio, this condition can be removed by setting {@link
|
||||
* EditedMediaItemSequence.Builder#setForceAudioTrack(boolean)} flag.
|
||||
* </ul>
|
||||
* <li>If a sequence starts with an HDR {@link EditedMediaItem}, all the following items in the
|
||||
* sequence must be HDR.
|
||||
|
@ -248,7 +248,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
sequenceAssetLoaders.add(
|
||||
new SequenceAssetLoader(
|
||||
sequence,
|
||||
composition.forceAudioTrack,
|
||||
assetLoaderFactory,
|
||||
new CompositionSettings(
|
||||
transformationRequest.hdrMode, composition.retainHdrFromUltraHdrImage),
|
||||
|
Loading…
x
Reference in New Issue
Block a user