如何在屏幕录制上绘图而不在屏幕上绘图?

时间:2021-05-05 22:50:07

标签: android kotlin drawing overlay android-mediaprojection

设置

我正在使用 MEDIA_PROJECTION_SERVICEMediaProjectionManagerMediaRecorder 来录制屏幕

请求

我正在尝试将简单形状的叠加添加到录音中,而这些形状不显示在屏幕上。

这里有人知道实现这一目标的最佳方法吗?

提案

我有一种感觉,我应该能够以某种方式创建第二个表面以添加到混合中,也许可以通过任何一个

  • 扩展 MediaRecorder 以添加第二个表面
  • 直接在 VirtualDisplay 的表面上绘图

...但我还没能管理它...

代码

我的录音代码如下:

    // Instance variables

    private var projectionManager: MediaProjectionManager? = null
    private var projection: MediaProjection? = null
    var display: VirtualDisplay? = null
    var recorder: MediaRecorder? = null
    var listener: RecorderListener? = null

    // Constants

    var virtualDisplayName = "a name"
    val failed = false
    val succeeded = true

    // Recorder setup

    val outputFormat = MediaRecorder.OutputFormat.MPEG_4
    val videoEncoder = MediaRecorder.VideoEncoder.DEFAULT
    val downsampleFactor = 0.5

    fun prepareToRecord(requestCode: Int, resultCode: Int, data: Intent?) : Boolean {
        projectionManager = context.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager?
        val metrics: DisplayMetrics = context.getResources().getDisplayMetrics()
        var downsampledDisplaySize = safelyDownSampledResolution(metrics)

        if (data == null) {
            // Recording permissions intent is missing
            return failed
        }
        if (projectionManager == null) {
            // Unable to get MediaProjectionManager service
            return failed
        }

        projection = projectionManager!!.getMediaProjection(resultCode, data)
        recorder = MediaRecorder()
        if (refreshRecorder(downsampledDisplaySize) == failed) {
            return failed
        }

        display = projection?.createVirtualDisplay(
                virtualDisplayName,
                downsampledDisplaySize.x,
                downsampledDisplaySize.y,
                metrics.densityDpi,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                recorder!!.surface,
                null,
                null)

        return succeeded
    }

    private fun setupRecorderWithoutAudio(displaySize: Point) {
        recorder?.setVideoSource(MediaRecorder.VideoSource.SURFACE)

        recorder?.setOutputFormat(outputFormat);
        recorder?.setVideoSize(displaySize.x, displaySize.y)

        recorder?.setVideoEncoder(videoEncoder);
    }

    private fun refreshRecorder(displaySize: Point) : Boolean {

        val parcelFileDescriptor = fileManager.getFileForRecorder(context)
        if (parcelFileDescriptor == null) return failed

        recorder?.setOutputFile(parcelFileDescriptor.fileDescriptor)
        setupRecorderWithoutAudio(displaySize)

        try {
            recorder?.prepare()
        }
        catch (exception: IllegalStateException) {

            // The recorder is in the incorrect state for this action
            // check the ORDERING of your initialization code
               
            return failed
        }
        catch (exception: IOException) {

            // Error preparing the recorder
            // check the CONFIGURATION chosen in your initialization code

            return failed
        }

        return succeeded
    }

0 个答案:

没有答案