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:
parent
b0f82767aa
commit
dfa98ae791
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user