-
Notifications
You must be signed in to change notification settings - Fork 86
Things LiTr Can Do
To change resolution and/or bitrate of a video track, we simply need to pass in an instance of MediaFormat
with required values:
Java:
MediaFormat videoFormat = MediaFormat.createVideoFormat("video/avc", 1280, 720);
videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, 9_000_000);
videoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 3);
videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
videoFormat.setInteger(KEY_ROTATION, 0)
Kotlin:
val videoFormat = MediaFormat.createVideoFormat("video/avc", 1280, 720)
.apply {
setInteger(MediaFormat.KEY_BIT_RATE, 9_000_000)
setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 3)
setInteger(MediaFormat.KEY_FRAME_RATE, 30)
setInteger(KEY_ROTATION, 0)
}
Values above will produce a "typical" 720p (HD) video track with landscape orientation in H.264 encoding. You can play with values to get the desired size/quality/orientation.
We can now pass the mediaFormat
as target video format in transform
API:
mediaTransformer.transform(
UUID.randomUUID.toString(),
sourceMediaUri,
targetFilePath,
videoFormat,
null,
listener,
null);
This should do the trick - every video track will be transcoded with provided parameters. We are passing null
for audio format, which means that audio track will be copied "as is". We are also passing null
for TransformationOptions
, which means that entire video will be transcoded and listener
will be called 100 times with progress update.
If you are using a TrackTransform
API, you should use videoFormat
when setting up TrackTransform
instance for a video track...
MediaSource = new MediaExtractorMediaSource(context, sourceUri);
MediaTarget = new MediaMuxerMediaTarget(outputFilePath, targetTrackCount, rotation, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
TrackTransform videoTrackTransform = new TrackTransform.Builder(mediaSource, sourceTrackIndex, mediaTarget)
.setTargetTrack(targetTrack)
.setDecoder(new MediaCodecDecoder())
.setEncoder(new MediaCodecEncoder())
.setRenderer(new GlVideoRenderer())
.build());
... and then pass it to transform
API that accepts TrackTransform
s:
List<TrackTransform> trackTransforms = new ArrayList<>();
trackTransforms.add(videoTrackTransform);
trackTransforms.add(audioTrackTransform);
mediaTransformer.transform(
UUID.randomUUID.toString(),
trackTransforms,
listener,
MediaTransformer.GRANULARITY_DEFAULT);
Using TrackTransform
API allows per-track manipulation - things like transcoding different video tracks with different resolution/bitrate, adding/removing tracks, using custom containers/decoders, etc.
Couple of notes on parameters:
- Video frame contents will be scaled to fit the target resolution. To avoid distortion, make sure that target video has the same aspect ratio as source video.
- Bitrate is provided in bps (bits per second) and determines the quality and size of target video. There is a helper method that will estimate that size, its underlying formula is simple:
size = bitrate * duration
. Keep in mind that parameter is in bits (not bytes) per second. - Lower bitrate will produce smaller size video, but may result in visual artifacts (blockiness, etc.) due to more aggressive compression. Inspect your transcoded videos visually while experimenting with bitrate/resolution especially with low bitrates.
- Smaller key frame interval will provide better seeking granularity/speed (seeking to key frames is quick) but will result in bigger file.
- Typical frame rate is 30. You might want to simply use frame rate of the source video.
- Rotation is specified in degrees in increments of 90 and defines orientation of target video: 0 - landscape, 90 - portrait, 180 - reverse landscape, 270 - reverse portrait. Resolution does not have to change when rotating a video: 1280x720 video with rotation of 90 will be played as a portrait video.
Similar to modifying video track, changing audio track parameters is also accomplished by creating and configuring an instance of MediaFormat
:
MediaFormat audioMediaFormat = MediaFormat.createAudioFormat("audio/mp4-latm", 48000, 2);
audioMediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 192_000);