Generate silent audio if no audio track is available.

To always generate silent audio, `removeAudio(true)` can be used in conjunction.

PiperOrigin-RevId: 502814315
This commit is contained in:
samrobinson 2023-01-18 10:20:26 +00:00 committed by christosts
parent b0f82767aa
commit dfa98ae791
9 changed files with 575 additions and 46 deletions

View File

@ -61,7 +61,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
public static final String SHOULD_REMOVE_AUDIO = "should_remove_audio";
public static final String SHOULD_REMOVE_VIDEO = "should_remove_video";
public static final String SHOULD_FLATTEN_FOR_SLOW_MOTION = "should_flatten_for_slow_motion";
public static final String FORCE_SILENT_AUDIO = "force_silent_audio";
public static final String GENERATE_SILENT_AUDIO = "generate_silent_audio";
public static final String AUDIO_MIME_TYPE = "audio_mime_type";
public static final String VIDEO_MIME_TYPE = "video_mime_type";
public static final String RESOLUTION_HEIGHT = "resolution_height";
@ -210,7 +210,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
private @MonotonicNonNull CheckBox removeAudioCheckbox;
private @MonotonicNonNull CheckBox removeVideoCheckbox;
private @MonotonicNonNull CheckBox flattenForSlowMotionCheckbox;
private @MonotonicNonNull CheckBox forceSilentAudioCheckbox;
private @MonotonicNonNull CheckBox generateSilentAudioCheckbox;
private @MonotonicNonNull Spinner audioMimeSpinner;
private @MonotonicNonNull Spinner videoMimeSpinner;
private @MonotonicNonNull Spinner resolutionHeightSpinner;
@ -271,7 +271,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
flattenForSlowMotionCheckbox = findViewById(R.id.flatten_for_slow_motion_checkbox);
forceSilentAudioCheckbox = findViewById(R.id.force_silent_audio_checkbox);
generateSilentAudioCheckbox = findViewById(R.id.generate_silent_audio_checkbox);
ArrayAdapter<String> audioMimeAdapter =
new ArrayAdapter<>(/* context= */ this, R.layout.spinner_item);
@ -382,7 +382,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
"removeAudioCheckbox",
"removeVideoCheckbox",
"flattenForSlowMotionCheckbox",
"forceSilentAudioCheckbox",
"generateSilentAudioCheckbox",
"audioMimeSpinner",
"videoMimeSpinner",
"resolutionHeightSpinner",
@ -402,7 +402,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
bundle.putBoolean(SHOULD_REMOVE_AUDIO, removeAudioCheckbox.isChecked());
bundle.putBoolean(SHOULD_REMOVE_VIDEO, removeVideoCheckbox.isChecked());
bundle.putBoolean(SHOULD_FLATTEN_FOR_SLOW_MOTION, flattenForSlowMotionCheckbox.isChecked());
bundle.putBoolean(FORCE_SILENT_AUDIO, forceSilentAudioCheckbox.isChecked());
bundle.putBoolean(GENERATE_SILENT_AUDIO, generateSilentAudioCheckbox.isChecked());
String selectedAudioMimeType = String.valueOf(audioMimeSpinner.getSelectedItem());
if (!SAME_AS_INPUT_OPTION.equals(selectedAudioMimeType)) {
bundle.putString(AUDIO_MIME_TYPE, selectedAudioMimeType);
@ -738,7 +738,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
@RequiresNonNull({
"removeVideoCheckbox",
"forceSilentAudioCheckbox",
"generateSilentAudioCheckbox",
"audioMimeSpinner",
"videoMimeSpinner",
"resolutionHeightSpinner",
@ -760,7 +760,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
@RequiresNonNull({
"removeAudioCheckbox",
"forceSilentAudioCheckbox",
"generateSilentAudioCheckbox",
"audioMimeSpinner",
"videoMimeSpinner",
"resolutionHeightSpinner",
@ -781,7 +781,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
}
@RequiresNonNull({
"forceSilentAudioCheckbox",
"generateSilentAudioCheckbox",
"audioMimeSpinner",
"videoMimeSpinner",
"resolutionHeightSpinner",
@ -793,7 +793,7 @@ public final class ConfigurationActivity extends AppCompatActivity {
"selectVideoEffectsButton"
})
private void enableTrackSpecificOptions(boolean isAudioEnabled, boolean isVideoEnabled) {
forceSilentAudioCheckbox.setEnabled(isVideoEnabled);
generateSilentAudioCheckbox.setEnabled(isVideoEnabled);
audioMimeSpinner.setEnabled(isAudioEnabled);
videoMimeSpinner.setEnabled(isVideoEnabled);
resolutionHeightSpinner.setEnabled(isVideoEnabled);

View File

@ -309,6 +309,8 @@ public final class TransformerActivity extends AppCompatActivity {
transformerBuilder
.setRemoveAudio(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_AUDIO))
.setRemoveVideo(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_VIDEO))
.experimentalSetGenerateSilentAudio(
bundle.getBoolean(ConfigurationActivity.GENERATE_SILENT_AUDIO))
.setEncoderFactory(
new DefaultEncoderFactory.Builder(this.getApplicationContext())
.setEnableFallback(bundle.getBoolean(ConfigurationActivity.ENABLE_FALLBACK))
@ -322,9 +324,6 @@ public final class TransformerActivity extends AppCompatActivity {
if (bundle.getBoolean(ConfigurationActivity.ENABLE_DEBUG_PREVIEW)) {
transformerBuilder.setDebugViewProvider(new DemoDebugViewProvider());
}
transformerBuilder.experimentalSetForceSilentAudio(
bundle.getBoolean(ConfigurationActivity.FORCE_SILENT_AUDIO));
}
return transformerBuilder

View File

@ -116,9 +116,9 @@
android:layout_weight="1">
<TextView
android:layout_gravity="center_vertical"
android:text="@string/force_silent_audio" />
android:text="@string/generate_silent_audio" />
<CheckBox
android:id="@+id/force_silent_audio_checkbox"
android:id="@+id/generate_silent_audio_checkbox"
android:layout_gravity="end" />
</TableRow>
<TableRow

View File

@ -66,7 +66,7 @@
<string name="permission_denied">Permission Denied</string>
<string name="hide_input_video">Hide input video</string>
<string name="show_input_video">Show input video</string>
<string name="force_silent_audio">Force silent audio</string>
<string name="generate_silent_audio">Generate silent audio</string>
<string name="overlay_alpha">Alpha</string>
<string name="overlay_uri">Uri</string>
<string name="bitmap_overlay_settings">Specify bitmap overlay settings</string>

View File

@ -0,0 +1,466 @@
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.64001F
maxInputSize = 36722
width = 1080
height = 720
frameRate = 29.970028
colorInfo:
colorSpace = 1
colorRange = 2
colorTransfer = 3
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 29, hash 4746B5D9
data = length 10, hash 7A0D0F2B
format 1:
sampleMimeType = audio/mp4a-latm
channelCount = 2
sampleRate = 44100
pcmEncoding = 2
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 0
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 23220
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 46440
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 69660
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 92880
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 116100
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 139320
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 162540
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 185760
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 208980
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 232200
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 255420
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 278640
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 301860
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 325080
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 348300
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 371520
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 394740
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 417960
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 441180
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 464400
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 487620
sample:
trackIndex = 0
dataHashCode = -770308242
size = 36692
isKeyFrame = true
presentationTimeUs = 0
sample:
trackIndex = 0
dataHashCode = -732087136
size = 5312
isKeyFrame = false
presentationTimeUs = 66733
sample:
trackIndex = 0
dataHashCode = 468156717
size = 599
isKeyFrame = false
presentationTimeUs = 33366
sample:
trackIndex = 0
dataHashCode = 1150349584
size = 7735
isKeyFrame = false
presentationTimeUs = 200200
sample:
trackIndex = 0
dataHashCode = 1443582006
size = 987
isKeyFrame = false
presentationTimeUs = 133466
sample:
trackIndex = 0
dataHashCode = -310585145
size = 673
isKeyFrame = false
presentationTimeUs = 100100
sample:
trackIndex = 0
dataHashCode = 807460688
size = 523
isKeyFrame = false
presentationTimeUs = 166833
sample:
trackIndex = 0
dataHashCode = 1936487090
size = 6061
isKeyFrame = false
presentationTimeUs = 333666
sample:
trackIndex = 0
dataHashCode = -32297181
size = 992
isKeyFrame = false
presentationTimeUs = 266933
sample:
trackIndex = 0
dataHashCode = 1529616406
size = 623
isKeyFrame = false
presentationTimeUs = 233566
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 510840
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 534059
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 557279
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 580499
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 603719
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 626939
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 650159
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 673379
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 696599
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 719819
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 743039
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 766259
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 789479
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 812699
sample:
trackIndex = 0
dataHashCode = 1949198785
size = 421
isKeyFrame = false
presentationTimeUs = 300300
sample:
trackIndex = 0
dataHashCode = -147880287
size = 4899
isKeyFrame = false
presentationTimeUs = 433766
sample:
trackIndex = 0
dataHashCode = 1369083472
size = 568
isKeyFrame = false
presentationTimeUs = 400400
sample:
trackIndex = 0
dataHashCode = 965782073
size = 620
isKeyFrame = false
presentationTimeUs = 367033
sample:
trackIndex = 0
dataHashCode = -261176150
size = 5450
isKeyFrame = false
presentationTimeUs = 567233
sample:
trackIndex = 0
dataHashCode = -1830836678
size = 1051
isKeyFrame = false
presentationTimeUs = 500500
sample:
trackIndex = 0
dataHashCode = 1767407540
size = 874
isKeyFrame = false
presentationTimeUs = 467133
sample:
trackIndex = 0
dataHashCode = 918440283
size = 781
isKeyFrame = false
presentationTimeUs = 533866
sample:
trackIndex = 0
dataHashCode = -1408463661
size = 4725
isKeyFrame = false
presentationTimeUs = 700700
sample:
trackIndex = 0
dataHashCode = 1569455924
size = 1022
isKeyFrame = false
presentationTimeUs = 633966
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 835919
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 859139
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 882359
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 905579
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 928799
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 952019
sample:
trackIndex = 1
dataHashCode = 1742602241
size = 4096
isKeyFrame = true
presentationTimeUs = 975239
sample:
trackIndex = 1
dataHashCode = 226248705
size = 448
isKeyFrame = true
presentationTimeUs = 998459
sample:
trackIndex = 0
dataHashCode = -1723778407
size = 790
isKeyFrame = false
presentationTimeUs = 600600
sample:
trackIndex = 0
dataHashCode = 1578275472
size = 610
isKeyFrame = false
presentationTimeUs = 667333
sample:
trackIndex = 0
dataHashCode = 1989768395
size = 2751
isKeyFrame = false
presentationTimeUs = 834166
sample:
trackIndex = 0
dataHashCode = -1215674502
size = 745
isKeyFrame = false
presentationTimeUs = 767433
sample:
trackIndex = 0
dataHashCode = -814473606
size = 621
isKeyFrame = false
presentationTimeUs = 734066
sample:
trackIndex = 0
dataHashCode = 498370894
size = 505
isKeyFrame = false
presentationTimeUs = 800800
sample:
trackIndex = 0
dataHashCode = -1051506468
size = 1268
isKeyFrame = false
presentationTimeUs = 967633
sample:
trackIndex = 0
dataHashCode = -1025604144
size = 880
isKeyFrame = false
presentationTimeUs = 900900
sample:
trackIndex = 0
dataHashCode = -913586520
size = 530
isKeyFrame = false
presentationTimeUs = 867533
sample:
trackIndex = 0
dataHashCode = 1340459242
size = 568
isKeyFrame = false
presentationTimeUs = 934266
released = true

View File

@ -64,15 +64,15 @@ import org.checkerframework.dataflow.qual.Pure;
long streamOffsetUs,
TransformationRequest transformationRequest,
ImmutableList<AudioProcessor> audioProcessors,
long forceSilentAudioDurationUs,
long generateSilentAudioDurationUs,
Codec.EncoderFactory encoderFactory,
MuxerWrapper muxerWrapper,
FallbackListener fallbackListener)
throws TransformationException {
super(inputFormat, streamStartPositionUs, muxerWrapper);
if (forceSilentAudioDurationUs != C.TIME_UNSET) {
silentAudioGenerator = new SilentAudioGenerator(inputFormat, forceSilentAudioDurationUs);
if (generateSilentAudioDurationUs != C.TIME_UNSET) {
silentAudioGenerator = new SilentAudioGenerator(inputFormat, generateSilentAudioDurationUs);
} else {
silentAudioGenerator = null;
}

View File

@ -88,7 +88,7 @@ public final class Transformer {
private ImmutableList<Effect> videoEffects;
private boolean removeAudio;
private boolean removeVideo;
private boolean forceSilentAudio;
private boolean generateSilentAudio;
private ListenerSet<Transformer.Listener> listeners;
@Nullable private AssetLoader.Factory assetLoaderFactory;
private FrameProcessor.Factory frameProcessorFactory;
@ -125,7 +125,7 @@ public final class Transformer {
this.videoEffects = transformer.videoEffects;
this.removeAudio = transformer.removeAudio;
this.removeVideo = transformer.removeVideo;
this.forceSilentAudio = transformer.forceSilentAudio;
this.generateSilentAudio = transformer.generateSilentAudio;
this.listeners = transformer.listeners;
this.assetLoaderFactory = transformer.assetLoaderFactory;
this.frameProcessorFactory = transformer.frameProcessorFactory;
@ -400,29 +400,32 @@ public final class Transformer {
}
/**
* Sets whether to force silent audio for the output file, ignoring any existing audio.
* Sets whether to generate silent audio for the output file, if there is no audio available.
*
* <p>This method is experimental and may be removed or changed without warning.
*
* <p>To replace existing audio with silence, call {@link #setRemoveAudio(boolean)} as well.
*
* <p>Audio properties/format:
*
* <ul>
* <li>Duration will match duration of the input media.
* <li>Sample mime type will match {@link TransformationRequest#audioMimeType}, or {@link
* MimeTypes#AUDIO_AAC} if {@code null}.
* <li>Sample rate will be 44100hz. This can be modified by passing a {@link
* <li>Sample rate will be {@code 44100} hz. This can be modified by passing a {@link
* SonicAudioProcessor} to {@link #setAudioProcessors(List)}, using {@link
* SonicAudioProcessor#setOutputSampleRateHz(int)}.
* <li>Channel count will be 2. This can be modified by implementing a custom {@link
* <li>Channel count will be {@code 2}. This can be modified by implementing a custom {@link
* AudioProcessor} and passing it to {@link #setAudioProcessors(List)}.
* </ul>
*
* @param forceSilentAudio Whether to output silent audio for the output file.
* @param generateSilentAudio Whether to generate silent audio for the output file if there is
* no audio track.
* @return This builder.
*/
@CanIgnoreReturnValue
public Builder experimentalSetForceSilentAudio(boolean forceSilentAudio) {
this.forceSilentAudio = forceSilentAudio;
public Builder experimentalSetGenerateSilentAudio(boolean generateSilentAudio) {
this.generateSilentAudio = generateSilentAudio;
return this;
}
@ -459,7 +462,7 @@ public final class Transformer {
videoEffects,
removeAudio,
removeVideo,
forceSilentAudio,
generateSilentAudio,
listeners,
assetLoaderFactory,
frameProcessorFactory,
@ -579,7 +582,7 @@ public final class Transformer {
private final ImmutableList<Effect> videoEffects;
private final boolean removeAudio;
private final boolean removeVideo;
private final boolean forceSilentAudio;
private final boolean generateSilentAudio;
private final ListenerSet<Transformer.Listener> listeners;
private final AssetLoader.Factory assetLoaderFactory;
private final FrameProcessor.Factory frameProcessorFactory;
@ -598,7 +601,7 @@ public final class Transformer {
ImmutableList<Effect> videoEffects,
boolean removeAudio,
boolean removeVideo,
boolean forceSilentAudio,
boolean generateSilentAudio,
ListenerSet<Listener> listeners,
AssetLoader.Factory assetLoaderFactory,
FrameProcessor.Factory frameProcessorFactory,
@ -607,10 +610,6 @@ public final class Transformer {
Looper looper,
DebugViewProvider debugViewProvider,
Clock clock) {
if (forceSilentAudio) {
removeAudio = true;
}
checkState(!removeVideo || !forceSilentAudio, "Silent only audio track needs a video track.");
checkState(!removeAudio || !removeVideo, "Audio and video cannot both be removed.");
this.context = context;
this.transformationRequest = transformationRequest;
@ -618,7 +617,7 @@ public final class Transformer {
this.videoEffects = videoEffects;
this.removeAudio = removeAudio;
this.removeVideo = removeVideo;
this.forceSilentAudio = forceSilentAudio;
this.generateSilentAudio = generateSilentAudio;
this.listeners = listeners;
this.assetLoaderFactory = assetLoaderFactory;
this.frameProcessorFactory = frameProcessorFactory;
@ -761,7 +760,7 @@ public final class Transformer {
videoEffects,
removeAudio,
removeVideo,
forceSilentAudio,
generateSilentAudio,
assetLoaderFactory,
frameProcessorFactory,
encoderFactory,

View File

@ -93,7 +93,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final TransformationRequest transformationRequest;
private final ImmutableList<AudioProcessor> audioProcessors;
private final ImmutableList<Effect> videoEffects;
private final boolean forceSilentAudio;
private final FrameProcessor.Factory frameProcessorFactory;
private final CapturingEncoderFactory encoderFactory;
private final Listener listener;
@ -108,6 +107,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final ConditionVariable transformerConditionVariable;
private final TransformationResult.Builder transformationResultBuilder;
private boolean generateSilentAudio;
private boolean isDrainingPipelines;
private @Transformer.ProgressState int progressState;
private @MonotonicNonNull RuntimeException cancelException;
@ -124,7 +124,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
ImmutableList<Effect> videoEffects,
boolean removeAudio,
boolean removeVideo,
boolean forceSilentAudio,
boolean generateSilentAudio,
AssetLoader.Factory assetLoaderFactory,
FrameProcessor.Factory frameProcessorFactory,
Codec.EncoderFactory encoderFactory,
@ -138,7 +138,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
this.transformationRequest = transformationRequest;
this.audioProcessors = audioProcessors;
this.videoEffects = videoEffects;
this.forceSilentAudio = forceSilentAudio;
this.generateSilentAudio = generateSilentAudio;
this.frameProcessorFactory = frameProcessorFactory;
this.encoderFactory = new CapturingEncoderFactory(encoderFactory);
this.listener = listener;
@ -373,9 +373,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
return;
}
this.trackCount.set(trackCount);
if (forceSilentAudio) {
this.trackCount.incrementAndGet();
}
}
@Override
@ -386,6 +383,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
long streamOffsetUs)
throws TransformationException {
if (!trackAdded) {
if (generateSilentAudio) {
if (this.trackCount.get() == 1 && MimeTypes.isVideo(format.sampleMimeType)) {
this.trackCount.incrementAndGet();
} else {
generateSilentAudio = false;
}
}
// Call setTrackCount() methods here so that they are called from the same thread as the
// MuxerWrapper and FallbackListener methods called when building the sample pipelines.
muxerWrapper.setTrackCount(trackCount.get());
@ -397,7 +402,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
getSamplePipeline(format, supportedOutputTypes, streamStartPositionUs, streamOffsetUs);
internalHandler.obtainMessage(MSG_REGISTER_SAMPLE_PIPELINE, samplePipeline).sendToTarget();
if (forceSilentAudio) {
if (generateSilentAudio) {
Format silentAudioFormat =
new Format.Builder()
.setSampleMimeType(MimeTypes.AUDIO_AAC)
@ -482,7 +487,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
streamOffsetUs,
transformationRequest,
audioProcessors,
forceSilentAudio ? durationUs : C.TIME_UNSET,
generateSilentAudio ? durationUs : C.TIME_UNSET,
encoderFactory,
muxerWrapper,
fallbackListener);
@ -528,7 +533,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
if (!audioProcessors.isEmpty()) {
return true;
}
if (forceSilentAudio) {
if (generateSilentAudio) {
return true;
}

View File

@ -271,10 +271,40 @@ public final class TransformerEndToEndTest {
}
@Test
public void startTransformation_silentAudio_completesSuccessfully() throws Exception {
public void startTransformation_silentAudioOnAudioOnly_isIgnored() throws Exception {
Transformer transformer =
createTransformerBuilder(/* enableFallback= */ false)
.experimentalSetForceSilentAudio(true)
.experimentalSetGenerateSilentAudio(true)
.build();
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_UNSUPPORTED_BY_ENCODER);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
DumpFileAsserts.assertOutput(
context, testMuxer, getDumpFileName(FILE_AUDIO_UNSUPPORTED_BY_ENCODER));
}
@Test
public void startTransformation_silentAudioOnAudioVideo_isIgnored() throws Exception {
Transformer transformer =
createTransformerBuilder(/* enableFallback= */ false)
.experimentalSetGenerateSilentAudio(true)
.build();
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
DumpFileAsserts.assertOutput(context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO));
}
@Test
public void startTransformation_silentAudioRemoveAudio_completesSuccessfully() throws Exception {
Transformer transformer =
createTransformerBuilder(/* enableFallback= */ false)
.experimentalSetGenerateSilentAudio(true)
.setRemoveAudio(true)
.build();
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO);
@ -285,6 +315,36 @@ public final class TransformerEndToEndTest {
context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".silentaudio"));
}
@Test
public void startTransformation_silentAudioRemoveVideo_isIgnored() throws Exception {
Transformer transformer =
createTransformerBuilder(/* enableFallback= */ false)
.experimentalSetGenerateSilentAudio(true)
.setRemoveVideo(true)
.build();
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
DumpFileAsserts.assertOutput(
context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".novideo"));
}
@Test
public void startTransformation_silentAudioOnVideoOnly_completesSuccessfully() throws Exception {
Transformer transformer =
createTransformerBuilder(/* enableFallback= */ false)
.experimentalSetGenerateSilentAudio(true)
.build();
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_VIDEO_ONLY);
transformer.startTransformation(mediaItem, outputPath);
TransformerTestRunner.runLooper(transformer);
DumpFileAsserts.assertOutput(
context, testMuxer, getDumpFileName(FILE_VIDEO_ONLY + ".silentaudio"));
}
@Test
public void startTransformation_adjustSampleRate_completesSuccessfully() throws Exception {
SonicAudioProcessor sonicAudioProcessor = new SonicAudioProcessor();