3

ユーザー インタラクションをビデオに記録して、ソーシャル メディア サイトにアップロードできるようにしたいと考えています。

たとえば、トーキング トム キャット Android アプリには小さなビデオカメラ アイコンがあります。ユーザーはビデオカメラのアイコンを押してからアプリを操作し、アイコンを押して録画を停止すると、ビデオが処理/変換されてアップロードの準備が整います。

setDrawingCacheEnabled(true) を使用して画像を保存できると思いますが、音声を追加する方法やビデオを作成する方法がわかりません。

更新:さらに読んだ後、NDK と ffmpeg を使用する必要があると思います。私はこれをしたくないのですが、他に選択肢がない場合、誰かがこれを行う方法を知っていますか?

Androidでこれを行う方法を知っている人はいますか?

関連リンク...

Android 画面のキャプチャまたは画像からのビデオの作成

Talking TomcatアプリケーションがiPhoneで行うように画面ビデオを記録する方法は?

4

1 に答える 1

8

MediaCodec APIを使用CONFIGURE_FLAG_ENCODEして、エンコーダーとして設定します。ffmpegは必要ありません:)

リンクした他の質問で画面を取得する方法をすでに見つけました。次に、キャプチャされた各フレームをにフィードしMediaCodec、適切なフォーマットフラグ、タイムスタンプなどを設定する必要があります。

編集:このためのサンプルコードを見つけるのは困難でしたが、ここでは、MartinStorsjöへのヒントです。クイック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
    }
}

いくつかの未解決の問題もあります。

編集:サポートされているピクセル形式の1つ(I420やNV12など)のバイトバッファーとしてデータをフィードします。残念ながら、特定のデバイスでどのフォーマットが機能するかを判断する完璧な方法はありません。ただし、カメラから取得できるのと同じ形式でエンコーダーを使用するのが一般的です。

于 2013-01-02T07:14:32.290 に答える