android - 从 android 中的屏幕抓取创建视频

标签 android video

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

例如,会说话的汤姆猫 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?

最佳答案

使用 MediaCodec带有 CONFIGURE_FLAG_ENCODE 的 API 可将其设置为编码器。不需要 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)将数据作为字节缓冲区输入。不幸的是,没有完美的方法来确定哪些格式适用于特定设备;然而,对于您可以从相机获得的相同格式与编码器一起使用是典型的。

关于android - 从 android 中的屏幕抓取创建视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14067339/

相关文章:

java - 无法找到或启动 Activity Intent

Android: 'Can' t 播放此视频'; MediaPlayer 和 VideoView 错误 1 ​​-38

c# - 同时解码和显示多个 H264 视频的最快方法 C#

iphone - 在 iOS 6 上嵌入 youtube 视频和自动播放不起作用

android - 应用程序未显示在全局快速搜索框中

android - 如何在 mpandroidchart 上设置自定义值 axisLeft

Android GDB 未加载 C++ 共享库

android - 在 sdk 中找不到 zipalign 工具

javascript - 正则表达式从YouTube获取get_video_info响应的一部分

.net - 如何转换为 m4v