【问题标题】:How to use Mediaprojection library in android to capture screen and convert into mp4 file?如何在 android 中使用 Mediaprojection 库捕获屏幕并转换为 mp4 文件?
【发布时间】:2015-06-12 15:24:20
【问题描述】:

从 android 5.0 开始,他们提供了 mediaprojection 库来捕获屏幕内容。但他们提供的示例演示应用程序尚不清楚。你可以找到示例应用程序here。在该应用程序中,他们使用 virtualdisplay 方法投影捕获的屏幕

private void setUpVirtualDisplay() {
    Log.i(TAG, "Setting up a VirtualDisplay: " +
            mSurfaceView.getWidth() + "x" + mSurfaceView.getHeight() +
            " (" + mScreenDensity + ")");
    mVirtualDisplay = mMediaProjection.createVirtualDisplay("ScreenCapture",
            mSurfaceView.getWidth(), mSurfaceView.getHeight(), mScreenDensity,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            mSurface, null, null);
    mButtonToggle.setText(R.string.stop);
}

我想将捕获的屏幕转换为我的屏幕录制应用程序的 mp4 文件。请帮我解决这个问题。

【问题讨论】:

    标签: android android-mediarecorder android-mediaprojection


    【解决方案1】:

    这里是示例代码参考from

    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
        private static final int PERMISSION_CODE = 1;
        private int mScreenDensity;
        private MediaProjectionManager mProjectionManager;
        private static final int DISPLAY_WIDTH = 480;
        private static final int DISPLAY_HEIGHT = 640;
        private MediaProjection mMediaProjection;
        private VirtualDisplay mVirtualDisplay;
        private MediaProjectionCallback mMediaProjectionCallback;
        private ToggleButton mToggleButton;
        private MediaRecorder mMediaRecorder;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);
            mScreenDensity = metrics.densityDpi;
    
            mMediaRecorder = new MediaRecorder();
            initRecorder();
            prepareRecorder();
    
            mProjectionManager = (MediaProjectionManager) getSystemService
                    (Context.MEDIA_PROJECTION_SERVICE);
    
            mToggleButton = (ToggleButton) findViewById(R.id.toggle);
            mToggleButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onToggleScreenShare(v);
                }
            });
    
            mMediaProjectionCallback = new MediaProjectionCallback();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            if (mMediaProjection != null) {
                mMediaProjection.stop();
                mMediaProjection = null;
            }
        }
    
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode != PERMISSION_CODE) {
                Log.e(TAG, "Unknown request code: " + requestCode);
                return;
            }
            if (resultCode != RESULT_OK) {
                Toast.makeText(this,
                        "Screen Cast Permission Denied", Toast.LENGTH_SHORT).show();
                mToggleButton.setChecked(false);
                return;
            }
            mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
            mMediaProjection.registerCallback(mMediaProjectionCallback, null);
            mVirtualDisplay = createVirtualDisplay();
            mMediaRecorder.start();
        }
    
        public void onToggleScreenShare(View view) {
            if (((ToggleButton) view).isChecked()) {
                shareScreen();
            } else {
                mMediaRecorder.stop();
                mMediaRecorder.reset();
                Log.v(TAG, "Recording Stopped");
                stopScreenSharing();
                initRecorder();
                prepareRecorder();
            }
        }
    
        private void shareScreen() {
            if (mMediaProjection == null) {
                startActivityForResult(mProjectionManager.createScreenCaptureIntent(), PERMISSION_CODE);
                return;
            }
            mVirtualDisplay = createVirtualDisplay();
            mMediaRecorder.start();
        }
    
        private void stopScreenSharing() {
            if (mVirtualDisplay == null) {
                return;
            }
            mVirtualDisplay.release();
            //mMediaRecorder.release();
        }
    
        private VirtualDisplay createVirtualDisplay() {
            return mMediaProjection.createVirtualDisplay("MainActivity",
                    DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
                    DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                    mMediaRecorder.getSurface(), null /*Callbacks*/, null /*Handler*/);
        }
    
        private class MediaProjectionCallback extends MediaProjection.Callback {
            @Override
            public void onStop() {
                if (mToggleButton.isChecked()) {
                    mToggleButton.setChecked(false);
                    mMediaRecorder.stop();
                    mMediaRecorder.reset();
                    Log.v(TAG, "Recording Stopped");
                    initRecorder();
                    prepareRecorder();
                }
                mMediaProjection = null;
                stopScreenSharing();
                Log.i(TAG, "MediaProjection Stopped");
            }
        }
    
        private void prepareRecorder() {
            try {
                mMediaRecorder.prepare();
            } catch (IllegalStateException e) {
                e.printStackTrace();
                finish();
            } catch (IOException e) {
                e.printStackTrace();
                finish();
            }
        }
    
        private void initRecorder() {
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mMediaRecorder.setVideoEncodingBitRate(512 * 1000);
            mMediaRecorder.setVideoFrameRate(30);
            mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
            mMediaRecorder.setOutputFile("/sdcard/capture.mp4");
        }
    }
    

    【讨论】:

    • 感谢 S.L.巴特。我已经添加了将 mp4 文件直接保存在 sdcard 中的完整代码。
    • 不适用于棉花糖,stop failed: -1007 视频文件 - 0 字节
    【解决方案2】:

    您将 Surface 从 SurfaceView 传递到 createVirtualDisplay()。将其替换为 Surface from a MediaRecorder

    【讨论】:

      【解决方案3】:

      看看这个POST。关于如何使用 MediaProjection API 将屏幕实际录制到外部存储上的 mp4 文件有一个很好的解释。此解决方案使用 MediaRecorder 来存储视频。

      您可以在Matt Snider的页面上找到另一个解决方案。 MediaMuxer 用于将视频存储到外部存储中。但请注意,MediaMuxer 的输出不可流式传输。

      【讨论】:

        猜你喜欢
        • 2012-07-06
        • 1970-01-01
        • 1970-01-01
        • 2012-04-14
        • 1970-01-01
        • 2015-11-21
        • 1970-01-01
        • 1970-01-01
        • 2012-01-16
        相关资源
        最近更新 更多