是否可以直接在 android 上录制 MJPEG?

Posted

技术标签:

【中文标题】是否可以直接在 android 上录制 MJPEG?【英文标题】:Is it possible to record MJPEG directly on android? 【发布时间】:2021-07-01 08:30:01 【问题描述】:

是否可以将 android 相机中的视频直接录制为 MJPEG?出于质量目的,我对 MJPEG 很感兴趣。我不想通过默认的 android 设置录制视频,然后转换为 MJPEG,而是直接从相机设备作为 MJPEG。这可能吗?我找不到任何表明这是可能的信息。

【问题讨论】:

ffmpeg -i input -c copy output 我不明白你的评论。你能详细说明一下吗? 不多赘述。 input 是相机或管道的路径。 -c copy 使用 stream copy 模式。 output 是输出。你的问题细节不多,所以我只是给你一个基本的建议。 【参考方案1】:

Kotlin 中的代码。

您只需在捕获请求上通过 setRepeatingRequest 获取连续图像。 调用 takeMJPEG,true 开始,false 停止。

使用 GOM 播放器打开生成的文件。我已经测试了实现。


    private val takeMJPEGSemaphore  = Semaphore(1)

    var mjpegBufferStream: BufferedOutputStream? = null
    var mjpegFileStream: FileOutputStream? = null
    var mjpegRecording = false


    override fun takeMJPEG(start: Boolean) 
        Log.i(TAG, "takeMJPEG start:$start")
        if (start) 
            takeMJPEGSemaphore.acquire()
            mjpegRecording = true
            val mjpegOutputFile = createFile(context, "mjpeg")
            mjpegFileStream = FileOutputStream(mjpegOutputFile)
            mjpegBufferStream = BufferedOutputStream(mjpegFileStream)
            // Clear imageReader
            var image: Image? = null
            do 
                image?.close()
                image = imageReader.acquireNextImage()
             while (image != null)
            session.stopRepeating()
            session.setRepeatingRequest(captureRequest.build(), null, cameraHandler)
            var count = 0
            var initialTime: Long = 0
            imageReader.setOnImageAvailableListener( reader ->
                image = reader.acquireNextImage()
                if (count == 0) 
                    initialTime = image!!.timestamp
                
                count++
                val buffer = image?.planes?.get(0)?.buffer
                val bytes = ByteArray(buffer!!.remaining()).apply  buffer.get(this) 
                mjpegBufferStream!!.write(bytes)
                mjpegBufferStream!!.flush()
                if (!mjpegRecording) 
                    imageReader.setOnImageAvailableListener(null, null)
                    session.stopRepeating()
                    session.setRepeatingRequest(previewRequest.build(), null, cameraHandler)
                    // Save the mjpeg file
                    mjpegBufferStream?.flush()
                    mjpegBufferStream?.close()
                    val finalTime = image!!.timestamp
                    Log.i(TAG, "saved mjpeg file with fps = $count / ((finalTime - initialTime) / 1000000000.0)")
                    takeMJPEGSemaphore.release()
                
                image?.close()
            , imageReaderHandler)
         else 
            mjpegRecording = false
            takeMJPEGSemaphore.acquire()
            takeMJPEGSemaphore.release()
        
    


        private fun createFile(context: Context, extension: String): File 
            val dir = File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DCIM), "Camera")
            if (!dir.exists()) 
                dir.mkdirs()
            
            return File.createTempFile(createFileName(), ".$extension", dir)
        
        private fun createFileName(): String 
            val sdf = SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS", Locale.US)
            return "IMG_$sdf.format(Date())"
        

【讨论】:

以上是关于是否可以直接在 android 上录制 MJPEG?的主要内容,如果未能解决你的问题,请参考以下文章

如何从我的 Android 设备直接在 Helix 服务器上录制视频?

在网页上录制音频 - iOS 和 Android

在android中使用OpenCV录制视频

ffmpeg 将 rtsp 重新流式传输到 mjpeg

从 Axis IP 摄像机重新流式传输 MJPEG

使用 AsyncTask 的 Android ICS 和 MJPEG