You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现横竖屏录制均输出固定横屏分辨率的视频?

问题需求

我需要实现:无论以竖屏还是横屏模式录制视频,输出的视频都保持固定的横屏分辨率(例如640×480)。

我尝试调用mediaRecorder.setVideoSize(640, 480)来设置固定分辨率,但竖屏录制时,输出视频的分辨率仍然是480×640,使用的代码如下:

mediaRecorder.setOutputFormat(camcorderProfile.fileFormat);
if (enableAudio) {
    mediaRecorder.setAudioEncoder(camcorderProfile.audioCodec);
    mediaRecorder.setAudioEncodingBitRate(camcorderProfile.audioBitRate);
    mediaRecorder.setAudioSamplingRate(camcorderProfile.audioSampleRate);
}
mediaRecorder.setVideoEncoder(camcorderProfile.videoCodec);
mediaRecorder.setVideoEncodingBitRate(camcorderProfile.videoBitRate);
mediaRecorder.setVideoFrameRate(camcorderProfile.videoFrameRate);
mediaRecorder.setVideoSize(640, 480);

我的预期是竖屏录制时,输出视频也能保持固定的横屏分辨率。此前在Stack Overflow找到过类似问题,但没有得到满意的解决方案。

在iOS端,我通过AVMutableVideoComposition在录制完成后对视频进行转换,实现了需求,代码如下:

let vComp = AVMutableVideoComposition()
vComp.renderSize = CGSize(width: CustomConsts.SAVE_WIDTH, height: CustomConsts.SAVE_HEIGHT)
vComp.frameDuration = CMTimeMake(value: 1, timescale: Int32(CustomConsts.SAVE_FRAME_RATE)) // fps

let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: vTrack.timeRange.duration)

let transformer = AVMutableVideoCompositionLayerInstruction(assetTrack: vTrack)
var videoSize = vTrack.naturalSize
videoSize = CGSize(width: videoSize.height, height: videoSize.width)
let ratio = CGFloat(CustomConsts.SAVE_WIDTH) / videoSize.width
let resizedVideoSize = CGSize(width: videoSize.width * ratio, height: videoSize.height * ratio)
let t1 = CGAffineTransform(rotationAngle: 90 * CGFloat.pi / 180)  
let t2 = CGAffineTransform(scaleX: ratio, y: ratio)
let t3 = CGAffineTransform(translationX: resizedVideoSize.width, y: -(resizedVideoSize.height - CGFloat(CustomConsts.SAVE_HEIGHT)) / 2)
transformer.setTransform(t1.concatenating(t2).concatenating(t3), at: CMTime.zero)
instruction.layerInstructions = [transformer]
vComp.instructions = [instruction]

请问Android端有没有类似的实现方式?


解决方案

Android端可以通过原生API或第三方库实现类似iOS的视频后期转码处理,以下是三种常用方案:

方案一:原生MediaCodec+MediaMuxer手动处理

通过提取原始视频帧,进行旋转、缩放变换后重新编码封装,核心步骤:

  1. 用MediaExtractor读取原始视频的轨道信息,获取宽高、旋转角度等参数。
  2. 初始化MediaCodec解码原始视频,得到可编辑的视频帧。
  3. 根据原始视频的旋转角度(竖屏录制通常为90/270度),将帧旋转为横屏方向,再缩放至目标分辨率(640×480)。
  4. 用另一个MediaCodec编码变换后的帧,最后通过MediaMuxer封装成最终视频文件。

核心代码片段:

// 提取视频基础信息
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(inputPath);
int videoTrackIndex = -1;
MediaFormat videoFormat = null;
for (int i = 0; i < extractor.getTrackCount(); i++) {
    MediaFormat format = extractor.getTrackFormat(i);
    String mime = format.getString(MediaFormat.KEY_MIME);
    if (mime.startsWith("video/")) {
        videoTrackIndex = i;
        videoFormat = format;
        break;
    }
}
extractor.selectTrack(videoTrackIndex);
int originalWidth = videoFormat.getInteger(MediaFormat.KEY_WIDTH);
int originalHeight = videoFormat.getInteger(MediaFormat.KEY_HEIGHT);
int rotation = videoFormat.containsKey(MediaFormat.KEY_ROTATION) ? videoFormat.getInteger(MediaFormat.KEY_ROTATION) : 0;

// 后续解码、帧变换、编码、封装逻辑需补充,可结合OpenGL ES实现高效的帧旋转缩放

方案二:AndroidX VideoEditor(Android 10+)

Android 10及以上版本提供的官方视频编辑库,可快速实现旋转、缩放、输出固定分辨率:

  1. 添加依赖:
implementation "androidx.video:video-editor:1.0.0-alpha08"
  1. 核心实现代码:
// 创建编辑会话
VideoEditor videoEditor = new VideoEditor(context);
MediaSource mediaSource = MediaSource.fromUri(context, Uri.parse(inputPath));
EditingSession editingSession = videoEditor.createEditingSession(mediaSource);

// 设置输出分辨率
OutputOptions outputOptions = new OutputOptions.Builder()
        .setOutputFormat(Muxer.OutputFormat.MPEG_4)
        .setResolution(new Size(640, 480))
        .build();

// 添加旋转+缩放变换
TransformEffect transformEffect = new TransformEffect.Builder()
        .setRotation(rotation) // 根据原始视频旋转角度设置,竖屏录制一般设为90
        .setScaleType(TransformEffect.ScaleType.FIT)
        .build();
editingSession.addEffect(transformEffect, TrackType.VIDEO);

// 执行导出
editingSession.startExport(outputOptions, outputPath, new ExportCallback() {
    @Override
    public void onExportProgress(float progress) {}
    @Override
    public void onExportCompleted() {}
    @Override
    public void onExportFailed(@NonNull ExportException exportException) {}
});

方案三:FFmpeg第三方库(兼容全版本)

通过FFmpeg命令行快速完成视频旋转、缩放和转码,适合低版本Android系统:

  1. 集成FFmpeg库:
implementation "com.arthenica:ffmpeg-kit:5.1.LTS"
  1. 执行转码命令:
// 竖屏转横屏+缩放到640×480
String command = "-i " + inputPath + " -vf \"transpose=1,scale=640:480\" -c:v libx264 -crf 23 -preset medium " + outputPath;
FFmpegKit.execute(command);
  • transpose=1:顺时针旋转90度(适配竖屏转横屏)
  • scale=640:480:缩放到目标分辨率
  • 可根据实际情况调整旋转参数(transpose=0逆时针90度,transpose=2顺时针180度等)

另外,你调用setVideoSize无效的原因是CamcorderProfile的参数会覆盖手动设置的分辨率,建议先调用setVideoSize,再配置CamcorderProfile相关参数,或者直接手动配置编码器参数,不依赖CamcorderProfile。


内容的提问来源于stack exchange,提问作者Vũ Thao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:05:19