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

Xamarin.Android中Camera2+MediaRecorder录制启动失败问题求助

问题描述

使用Xamarin.Android的Camera2组件开发短视频录制应用,调用后置摄像头,已成功选择并打开相机,但调用mediaRecorder.Start()时抛出Java.Lang.RuntimeException: start failed,伴随扬声器响声,测试设备为Techno Spark 4(Android 9)。

已实现的相机初始化代码:

// Create an instance of CameraManager
CameraManager manager = (CameraManager)Android.App.Application.Context.GetSystemService(Context.CameraService);

string cameraId = null;

// Get the ID of the back-facing camera
App.cameraId = manager.GetCameraIdList().FirstOrDefault(id => (int)manager.GetCameraCharacteristics(id).Get(CameraCharacteristics.LensFacing) == (int)LensFacing.Back);

// Create an instance of CameraDevice
CameraDevice cameraDevice = null;
manager.OpenCamera(cameraId, new MyCameraDeviceStateCallback(this), null);

MediaRecorder配置代码:

// Create a new instance of MediaRecorder
MediaRecorder mediaRecorder = new MediaRecorder();

// Set the video source to the camera
mediaRecorder.SetVideoSource(VideoSource.Camera);

// Set the output format and file path
mediaRecorder.SetOutputFormat(OutputFormat.Default);
mediaRecorder.SetOutputFile(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal).ToString() + "/video.mp4");

// Set the video encoder
mediaRecorder.SetVideoEncoder(VideoEncoder.Default);

// Prepare and start recording
mediaRecorder.Prepare();
mediaRecorder.Start();

错误栈信息:

Java.Lang.RuntimeException: start failed.
at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod(...)
at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualVoidMethod(...)
at Android.Media.MediaRecorder.Start ()
...
--- End of managed Java.Lang.RuntimeException stack trace ---
java.lang.RuntimeException: start failed.
at android.media.MediaRecorder.start(Native Method)

原因分析
  1. Camera2与MediaRecorder未绑定:Camera2组件需要将相机输出Surface与MediaRecorder的Surface关联,直接启动MediaRecorder会导致相机资源未正确分配。
  2. MediaRecorder配置不完整:缺少视频尺寸、帧率等关键参数,Android 9设备对MediaRecorder的配置要求更严格,使用Default选项可能无法匹配相机硬件支持的格式。
  3. 相机会话未正确初始化:CameraDevice打开后需创建CameraCaptureSession,并将MediaRecorder的Surface加入会话配置,否则相机无法向MediaRecorder输出数据。
  4. 权限与路径问题:需确保已申请CAMERA和RECORD_AUDIO权限(即使不录制音频,部分设备仍需该权限),同时确认文件路径可写入。
解决步骤

1. 完善权限配置

在AndroidManifest.xml中添加必要权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

运行时动态申请权限(Android 6+):

if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) != Permission.Granted ||
    ContextCompat.CheckSelfPermission(this, Manifest.Permission.RecordAudio) != Permission.Granted)
{
    ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.Camera, Manifest.Permission.RecordAudio }, 100);
}

2. 正确关联Camera2与MediaRecorder

修改MyCameraDeviceStateCallback,在相机打开后创建CaptureSession并绑定MediaRecorder的Surface:

public class MyCameraDeviceStateCallback : CameraDevice.StateCallback
{
    private readonly YourActivity _activity;
    private CameraDevice _cameraDevice;
    private MediaRecorder _mediaRecorder;

    public MyCameraDeviceStateCallback(YourActivity activity)
    {
        _activity = activity;
    }

    public override void OnOpened(CameraDevice camera)
    {
        _cameraDevice = camera;
        InitializeMediaRecorder();
        CreateCaptureSession();
    }

    private void InitializeMediaRecorder()
    {
        _mediaRecorder = new MediaRecorder();

        _mediaRecorder.SetVideoSource(VideoSource.Camera);
        _mediaRecorder.SetOutputFormat(OutputFormat.Mpeg4);
        string outputPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "video.mp4");
        _mediaRecorder.SetOutputFile(outputPath);

        // 获取相机支持的视频尺寸
        var characteristics = _activity.GetSystemService<CameraManager>().GetCameraCharacteristics(App.cameraId);
        var configs = characteristics.Get(CameraCharacteristics.ScalerStreamConfigurationMap);
        var videoSize = configs.GetOutputSizes(Class.FromType(typeof(MediaRecorder)))[0];

        _mediaRecorder.SetVideoSize(videoSize.Width, videoSize.Height);
        _mediaRecorder.SetVideoFrameRate(30);
        _mediaRecorder.SetVideoEncoder(VideoEncoder.H264);
        
        // 可选:若不需要音频可注释,但部分设备需保留
        _mediaRecorder.SetAudioSource(AudioSource.Mic);
        _mediaRecorder.SetAudioEncoder(AudioEncoder.Aac);

        try
        {
            _mediaRecorder.Prepare();
        }
        catch (IOException ex)
        {
            // 处理准备失败异常
        }
    }

    private void CreateCaptureSession()
    {
        Surface recorderSurface = _mediaRecorder.Surface;
        List<Surface> surfaces = new List<Surface> { recorderSurface };

        _cameraDevice.CreateCaptureSession(surfaces, new CameraCaptureSession.StateCallback()
        {
            public override void OnConfigured(CameraCaptureSession session)
            {
                try
                {
                    var captureRequestBuilder = _cameraDevice.CreateCaptureRequest(CameraTemplate.Record);
                    captureRequestBuilder.AddTarget(recorderSurface);
                    captureRequestBuilder.Set(CaptureRequest.ControlAfMode, (int)ControlAFMode.ContinuousVideo);

                    session.SetRepeatingRequest(captureRequestBuilder.Build(), null, null);
                    _mediaRecorder.Start();
                }
                catch (Exception ex)
                {
                    // 处理启动失败异常
                }
            }

            public override void OnConfigureFailed(CameraCaptureSession session)
            {
                // 处理会话配置失败
            }
        }, null);
    }

    // 实现OnDisconnected、OnError等回调方法省略
}

3. 清理资源

录制结束后,正确释放MediaRecorder和Camera资源:

private void StopRecording()
{
    try
    {
        _mediaRecorder.Stop();
        _mediaRecorder.Reset();
        _mediaRecorder.Release();
    }
    catch (Exception ex)
    {
        // 处理停止异常
    }

    _cameraDevice.Close();
}
关键注意点
  • 必须在CameraDevice.StateCallback.OnOpened回调中初始化MediaRecorder,避免相机未完全就绪时操作。
  • 使用相机硬件支持的视频尺寸,避免直接设置不兼容的参数。
  • Android 9设备需明确指定MediaRecorder的格式、编码器,避免使用Default选项。

内容的提问来源于stack exchange,提问作者Md Idiake

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 06:42:05