【问题标题】:Create video from screen grabs in android从android中的屏幕抓取创建视频
【发布时间】:2012-12-28 09:29:13
【问题描述】:

我想在视频中记录用户互动,然后人们可以上传到他们的社交媒体网站。

例如,会说话的汤姆猫 Android 应用程序有一个小摄像机图标。用户可以按下摄像机图标,然后与应用程序交互,按下图标停止录制,然后处理/转换视频以供上传。

我想我可以使用 setDrawingCacheEnabled(true) 来保存图像,但不知道如何添加音频或制作视频。

更新:进一步阅读后,我认为我需要使用 NDK 和 ffmpeg。我不想这样做,但是,如果没有其他选择,有人知道该怎么做吗?

有谁知道如何在 Android 中做到这一点?

相关链接...

Android Screen capturing or make video from images

how to record screen video as like Talking Tomcat application does in iphone?

【问题讨论】:

    标签: android video


    【解决方案1】:

    使用MediaCodec API 和CONFIGURE_FLAG_ENCODE 将其设置为编码器。不需要 ffmpeg :)

    您已经在链接到的另一个问题中找到了如何抓取屏幕,现在您只需将每个捕获的帧提供给MediaCodec,设置适当的格式标志、时间戳等。

    编辑: 很难找到此示例代码,但 here it is,向 Martin Storsjö 致敬。快速 API 演练:

    MediaFormat inputFormat = MediaFormat.createVideoFormat("video/avc", width, height);
    inputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
    inputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
    inputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
    inputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 75);
    inputFormat.setInteger("stride", stride);
    inputFormat.setInteger("slice-height", sliceHeight);
    
    encoder = MediaCodec.createByCodecName("OMX.TI.DUCATI1.VIDEO.H264E"); // need to find name in media codec list, it is chipset-specific
    
    encoder.configure(inputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    encoder.start();
    encoderInputBuffers = encoder.getInputBuffers();
    encoderOutputBuffers = encoder.getOutputBuffers();
    
    byte[] inputFrame = new byte[frameSize];
    
    while ( ... have data ... ) {
        int inputBufIndex = encoder.dequeueInputBuffer(timeout);
    
        if (inputBufIndex >= 0) {
            ByteBuffer inputBuf = encoderInputBuffers[inputBufIndex];
            inputBuf.clear();
    
            // HERE: fill in input frame in correct color format, taking strides into account
            // This is an example for I420
            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    inputFrame[ i * stride + j ] = ...; // Y[i][j]
                    inputFrame[ i * stride/2 + j/2 + stride * sliceHeight ] = ...; // U[i][j]
                    inputFrame[ i * stride/2 + j/2 + stride * sliceHeight * 5/4 ] = ...; // V[i][j]
                }
            }
    
            inputBuf.put(inputFrame);
    
            encoder.queueInputBuffer(
                inputBufIndex,
                0 /* offset */,
                sampleSize,
                presentationTimeUs,
                0);
        }
    
        int outputBufIndex = encoder.dequeueOutputBuffer(info, timeout);
    
        if (outputBufIndex >= 0) {
            ByteBuffer outputBuf = encoderOutputBuffers[outputBufIndex];
    
            // HERE: read get the encoded data
    
            encoder.releaseOutputBuffer(
                outputBufIndex, 
                false);
        }
        else {
            // Handle change of buffers, format, etc
        }
    }
    

    还有一些open issues

    编辑:您可以将数据作为字节缓冲区以一种受支持的像素格式(例如 I420 或 NV12)输入。不幸的是,没有完美的方法来确定哪些格式可以在特定设备上运行。但是,对于您可以从相机获得的与编码器一起使用的相同格式,这是典型的。

    【讨论】:

    • 谢谢,会检查一下。
    • 您好,研究了一下,但没有很多例子。我如何将每个捕获的帧实际输入 MediaCodec?
    • 嗨,Alex,感谢您提供所有代码。假设我有一系列图像,比如 image01.png、image02.png 等,每一个都将分配给变量“inputFrame”,然后最终放入 ByteBuffer 变量“inputBuf”?
    • @Mel:是的,但是图像需要转换为正确色彩空间中的像素数组,您不能只将它们分配给 inputFrame 而不进行转换。我在上面展示了如何将 Y、U、V 颜色空间中的像素数组打包到 inputFrame 中;要从 png 开始,您需要 (a) 将 png 解码为 RGB 像素数组,以及 (b) 将每个像素从 RGB 转换为 YUV;然后按上图打包。
    • 有没有办法在android上做同样的事情?
    猜你喜欢
    • 2012-01-27
    • 1970-01-01
    • 2017-03-05
    • 2011-03-06
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 2011-07-19
    相关资源
    最近更新 更多