MediaRecorder 和 VideoSource.SURFACE,停止失败:-1007(严重的 Android bug)

2023-11-22

我正在尝试记录MediaRecorder不使用Camera实例但使用Surface视频源(是的,这是可能的,但事实证明它并不那么完美)-mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

我只是写下问题所在:

下一个代码仅在某些设备上有效,并且在最近设备重新启动后在某些设备上临时有效或根本不起作用

如果不行的话MediaRecorder.stop()方法失败并出现下一个错误

E/MediaRecorder:停止失败:-1007 W/System.err:

java.lang.RuntimeException:停止失败。在

android.media.MediaRecorder.stop(本机方法)

录音机 mp4 文件太小(千字节),无法播放

测试设备:

适用于联想 P2、小米 A1

不适用于小米红米 5、索尼 Xperia、小米红米 4 Prime

您也可以阅读我的代码中的注释以更好地理解问题

new Thread(() -> {

    MediaRecorder mediaRecorder = new MediaRecorder();

    File file = new File(Environment.getExternalStorageDirectory()
            + File.separator + "test_media_recorder_surface_source.mp4");
    if (file.exists()) {
        file.delete();
    }

    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mediaRecorder.setOutputFile(file.getAbsolutePath());
    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    mediaRecorder.setVideoSize(1280, 720);
    mediaRecorder.setCaptureRate(24);

    try {
        mediaRecorder.prepare();

        int sleepTime = 1000 / 24;

        Surface surface = mediaRecorder.getSurface();

        mediaRecorder.start();

        // record something (we can also record frames here from onPreviewFrame byte arrays)
        // e.g. convert raw frame byte[] to Bitmap using mb OpenCV and then draw bitmap on canvas
        // using canvas.drawBitmap(...)
        // here we record just blue background...
        for (int i = 0; i < 120; i++) { // 5 seconds, 24 fps
            Canvas canvas = surface.lockCanvas(null);
            canvas.drawColor(Color.BLUE);
            surface.unlockCanvasAndPost(canvas);
            try {
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // on many devices stop fails with RuntimeException -1007 error code
        // I guess it works ok 100% only for modern powerful devices...
        mediaRecorder.stop();
        // E/MediaRecorder: stop failed: -1007
        // W/System.err: java.lang.RuntimeException: stop failed.
        // at android.media.MediaRecorder.stop(Native Method)

        // recorder.reset();
        mediaRecorder.release();
        // I get file with very small size (kilobytes) and it can't be played

        // ######## RESULTS ######

        // WORKS OK ON:
        // - Lenovo P2 (Android 7)
        // - Xiaomi Mi A1 (Android 8)

        // DOESN'T WORK ON (stop fails with -1007, small video file and can't be played):
        // - Xiaomi Redmi 5 (Android 7)
        // - Sony Xperia (I don't remember the exact model and Android OS)
        // - Xiaomi Redmi 4 Prime (Android 6) *

        // * p.s. on Xiaomi Redmi 4 Prime it works some time after rebooting the device
        // if I leave this smartphone for a while and try again it will fail again
        // until I reboot the device...

    } catch (Exception e) {
        e.printStackTrace();
    }
}).start();

更新#1似乎取得了一些进展可能是什么问题 - 代码问题(mp4/h264)

与 WEBM/VP8 配合使用效果更好,现在可以播放视频,但 fps 出现问题,比例显示为 1000

mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.WEBM);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.VP8);

MediaRecord 在使用时也不录制音频

mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.VORBIS);

check 使用 MP4/H264 且分辨率大于 720p 时,Android MediaRecorder 在停止时崩溃所以当你使用时也会发生MediaRecorder and MediaProjection记录/捕获设备屏幕(因为它还使用Surface...)

UPDATE 2是的,似乎 vp8 编解码器工作正常,但 webm 容器有一个问题 - 没有音频!

有缺陷的 Android 只是不支持 VORBIS/OGG 音频编码...https://developer.android.com/guide/topics/media/media-formats#audio-formats


我想没有解决办法

所以答案是:MediaRecorder/Android 存在缺陷,或者移动公司在开发设备时并不关心所有 Android 功能

Update

MediaCodec也有帆布车

mSurface = mMediaCodec.createInputSurface();
mSurface.lockHardwareCanvas()

它适用于更多带有 MediaCodec 的设备,但仍有一些设备可能无法使用此方法正确录制视频

So 最终答案: 永远不要使用lockCanvas or lockHardwareCanvas当与MediaCodec or MediaRecorder,有bug..

唯一的方法——OpenGl ES

有关问题的其他链接:

https://github.com/googlesamples/android-Camera2Video/issues/86 https://issuetracker.google.com/issues/111433520

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MediaRecorder 和 VideoSource.SURFACE,停止失败:-1007(严重的 Android bug) 的相关文章

  • 在 Android Pie 上启动 context.startService(intent)

    我在 Activity 的 onResume 上启动了一项服务 它在 Oreo 上运行良好 但最近我看到 Android P 崩溃 显示 无法恢复 Activity 不允许启动服务意图 应用程序在后台 有没有人以前见过这个并且能够应用修复
  • 为什么我们(必须)使用不同的启动器图标(xhdpi、hdpi 等)

    我想知道 为什么我们在 android 中使用不同的启动器图标 大小 目前您 必须 将图标大小调整为 LDPI 36 x 36 MDPI 48 x 48 HDPI 72 x 72 XHDPI 96 x 96 并将它们放入所需的文件夹中 但是
  • 如何从色彩校正增益获得色温

    我想找出相机拍摄的照片的色温 final CameraCaptureSession CaptureCallback previewSSession new CameraCaptureSession CaptureCallback Overr
  • Firebase 存储 URL 不断随着新令牌的变化而变化

    我正在尝试使用 firebase 数据库和存储构建社交媒体应用程序 以下是预期的流程 用户上传个人资料图片 该图片存储在当前用户文件夹中的 Firebase 存储中 并且 URL 存储在 Firebase 数据库中以便快速访问 工作正常 用
  • RecyclerView 滚动不适用于 NestedScrollView

    我有一个布局 其中有一个 NestedScrollView 其中包含一个图像 多个按钮和一个 RecycleView 当我说recyclerView smoothScrollToPosition or recyclerView scroll
  • 此 TableLayout 布局或其 LinearLayout 父级无用如何解决此警告

    我在 Linearlayout 中有 tablelayout 但它向我显示了此警告消息这个TableLayout布局或其LinearLayout父级是没有用的 如何克服这个警告可以帮助我 提前致谢
  • 如何删除带有操作栏、视图页面和多个片段的选项卡?

    我正在使用我找到的代码here https stackoverflow com questions 10082163 actionbarsherlock tabs multi fragments public class ActionBar
  • java.io.IOException:无法打开同步连接!进入 Nexus [重复]

    这个问题在这里已经有答案了 我尝试在 Eclipse 上运行我的应用程序 但发现了这些错误 这是第一次遇到 所以请给我关于这些错误的任何想法 我目前使用的是 Nexus 手机 2011 08 04 15 59 09 App Android
  • 未定义的参考错误 - rand

    我正在创建一个命令行 C 测试应用程序 可执行 以便在我的 root Android 设备上运行 该可执行文件使用多个预构建的 C 库 其中之一使用 rand 在链接状态期间我收到错误 rand 的未定义引用 为了检查路径是否设置正确 我尝
  • 如何读取其他应用程序的SharedPreferences(相同用户ID)?

    在安卓4 3上测试 我有两个应用程序 com my app first and com my app second 在我的活动中 我想读取其他应用程序的首选项 我选择对我的两个应用程序使用相同的用户 ID android sharedUse
  • Android Google 地图:隐藏整个地图的多边形或形状

    我试图隐藏除一个区域之外的整个地图 因为我使用的多边形在我想要显示的区域中有一个洞 问题在于 根据缩放的不同 空白区域会被多边形的颜色覆盖 或者多边形会失去其颜色 这是代码 polygon hide all world map float
  • Android imageview 改变色调来模拟按钮点击

    我有一个图像视图 我在其中设置了从网址获取的位图 在 imageview 上 我设置了一个 onClickListener 来打开一个对话框 当按下图像视图时 我想以某种方式改变色调 使其更暗 以提供一种类似按钮点击的感觉 你有什么建议 h
  • 在 Android 上获取一个滚动到 GridView 底部视图的按钮

    我正在尝试将现有的 iPhone 应用程序移植到 Android 我希望有一个按钮滚动到 GridView 底部的视图中 以使用户能够从服务器加载更多数据 目前 我的解决方案只是修复屏幕底部的一个按钮 而不是让它滚动到视图中 这是我的布局代
  • Android 中的 FFMpeg jni?

    我已经构建了 Bambuser http bambuser com opensource 提供的 FFMPEG 可执行文件和库 所以我设法构建了 Android 可执行文件和库 如何在 Eclipse 项目中链接这些库并从 Java 调用
  • Google Analytics 点击已发送,但在 Analytics 控制台上不可见

    我一直在尝试按照 Google 官方文档中的步骤在我的应用程序中实现 Google Analytics 完成编码部分后 我转到分析控制台以查看是否收到任何点击 我等了将近2天 但没有看到任何进展 然后我尝试在 logcat 中使用 GAv4
  • gradle 复制为 doLast 不起作用

    我正在尝试做一件非常简单的事情 由于 gradle 在清理时会删除构建目录中的所有文件 因此我想在创建发布版本时将 apk 移至其他位置 所以我在链中添加了一个复制任务 并将其设置为最后一个 我尝试过的任何方法都不起作用 所以我简化了它并添
  • 使用 Lint 和 SonarQube 分析 Android 项目

    我真的 溢出 了试图让这些东西一起工作 我按照这里的指示进行操作 http docs sonarqube org display PLUG Android Lint Plugin http docs sonarqube org displa
  • Android facebook api,获取不同尺寸的头像

    我正在使用相对较新的 Facebook 图形 api 我正在获取使用该应用程序的朋友列表及其个人资料照片 我不知道如何修改我发送的参数 以便返回的图片很大 当前返回的默认值很小 我正在使用 newMyFriendsRequest 我发送的参
  • Android 以编程方式停止 toast 通知?

    有没有办法以编程方式停止 Toast 消息 假设我有一个按钮 单击它可以滚动 toast 消息 并且在 onclick 事件中我想停止队列中的所有消息并只显示新消息 我该怎么做 我的代码的简化版本如下 代码 public class Hel
  • Android 多点触控

    因此 我尝试使用 onTouchEvent 检查多个屏幕触摸 但它似乎仍然只读取第一次触摸 有人可以帮忙吗 这是我的代码 public boolean onTouchEvent MotionEvent e int num e getPoin

随机推荐