23

同じ問題を抱えた 2 つの異なるコード ベースがあります。

最初のものは、developer.android.com から直接コピーされたコードです: http://developer.android.com/guide/topics/media/camera.html#custom-camera

2 つ目は次のコードです。

http://android-er.blogspot.com.au/2011/10/simple-exercise-of-video-capture-using.html

どちらも通常の背面カメラでは問題なく動作しますが、前面カメラを使用しようとするとすぐにエラーが発生します。

これは、次のデバイスで発生します。

  • ネクサス S 4.1.2

  • ギャラクシー ネクサス 4.1.2

  • Nexus 7 4.2.1 (前面カメラのみ)

2.2 時代の Camera Params のように見えるものも試してみました。Samsung や HTC の一部のデバイスでは必要であると主張する人もいますが、複数の異なる記事で異なる文字列キーが参照されています。

c = Camera.open(frontFacingCameraID); // attempt to get a Camera instance
Camera.Parameters params = c.getParameters();
params.set("cam-mode", 1);
params.set("cam_mode", 1);
params.set("camera-id", 1);
c.setParameters(params);

これらはどれも機能しません。Nexus 7 ではもちろん 0 である正しい前面カメラ ID を検出していることにも注意してください。しかし、結果はすべてのデバイスで同じです。

低品質のプロファイルを使用してみました。ビデオの解像度、エンコーダ、出力形式、ビットレート、フレーム レート、およびビデオ サイズをさまざまな方法で手動で設定しようとしましたが、どれもうまくいきませんでした。

ほとんどのコードで何も問題がないと思わせるのは、通常のカメラが正常に動作することです。私の推測では、Media Recorder をセットアップする prepareVideoRecorder() / prepareMediaRecorder() メソッドと関係があると思います。

おそらく、前面カメラで動作することが知られている Media Recorder の手動エンコード設定ですか?

私が言わなければならないのは、Android Camera と MediaRecorder API は最悪です。iOS と比較すると、少し混乱しています。言うまでもなく、いくつかの恐ろしく見えるパラメータの非互換性の問題や、断片化されたデバイス環境全体での異なる解像度は言うまでもありません。

JB デバイスで動作させることができると仮定すると、これらの問題のほとんどが API 15 ICS で解決されるかどうかを経験から知っている人はいますか?

API 10 Gingerbread のサポートが難しい場合は、サポートしないことを検討します。

4

6 に答える 6

39

今日もこの問題に少し取り組みました。

まず、権限が正しく設定されていることを確認してください。具体的には、ビデオを録画するには、次のものが必要です。

<uses-feature android:name="android.hardware.camera.front" />
<uses-feature android:name="android.hardware.microphone"/>

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

第二に、これはトリッキーな部分です。チュートリアルのこの行は、前面カメラでは機能しません!

mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

CamcorderProfile.get() の署名は、デフォルトで背面カメラのプロファイルになります。

指定された品質レベルで、デバイスの最初の背面カメラのカムコーダー プロファイルを返します。デバイスに背面カメラがない場合、これは null を返します。

代わりに、http://developer.android.com/reference/android/media/CamcorderProfile.html#get(int,%20int)を使用してください。最初のパラメーターは、開いたカメラの ID、具体的には前面カメラです。

于 2013-03-04T17:42:15.837 に答える
26

わかりましたので、ようやく機能するようになりました。

この問題はProfile Settings、特にFrame Rate.

私のプライマリ テスト デバイスである Nexus S で、カメラをプローブすると、次のパラメータが表示されます。

リアカメラの場合:
15 FPS から 30 FPS で十分です。

正面カメラの場合:
7.5 FPS から 30 FPS で十分です。

次に、使用しようとしているプロファイルを確認します。

CamcorderProfile.QUALITY_HIGH
CamcorderProfile.QUALITY_LOW

QUALITY_LOW:

audioBitRate: 12200
audioChannels: 1
audioCodec: AMR_NB audioSampleRate: 8000
duration: 30
fileFormat: THREE_GPP
quality: 0
videoBitRate: 256000
videoCodec: H264
videoFrameRate: 30
videoFrameWidth: 176
videoFrameHeight: 144

QUALITY_HIGH:

audioBitRate: 24000
audioChannels: 1
audioCodec: AAC
audioSampleRate: 16000
duration: 60
fileFormat: MPEG_4
quality: 1
videoBitRate: 3000000
videoCodec: H264
videoFrameRate: 30
videoFrameWidth: 720
videoFrameHeight: 480

前面が 640x480 しかないことから、明らかに、高品質プロファイルは背面カメラ用です。しかし、どちらも 30 FPS を示しています。

今....ここに奇妙さがあります:

背面カメラに任意のフレームレートを設定すると、プロファイルに関係なく、恐ろしいクラッシュが発生します。

-19 エラー

mediaRecorder.setVideoFrameRate(fpsInt);

リアカメラは気にしないので大したことではありませんが、プロファイルがデフォルトで 30 に設定されており、Params15-30 を受け入れると言っていることを考えると、それは奇妙です. しかし、私が試した int 値は機能しませんでした。省略してsetVideoFrameRateも大丈夫です。

とにかく、正面カメラに移ります。

したがって、QUALITY_LOWプロファイルを使用してフレームレートを 15 以下に設定すると、魔法のように機能します。

mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
mediaRecorder.setVideoFrameRate(15);

実際には、1 ~ 15 の任意の値が機能します。これは奇妙に思えます。

ここに難問があります。おそらく解像度を調べて、ほとんどのカメラに適切な解像度を選択できますが、ほとんどすべての前面カメラが最小 VGA 640x480 であると確信しています。

しかし、フレームレートはどうですか?Nexus S の場合、推測するだけで 15 以下の値を判断できる方法はありませんか? カメラから返される最低のフレームレートを常に使用することを目指す必要がありますか?

Galaxy Nexus を調べたところ、3 つのフレーム レート範囲があり、最初のフレーム レートは 15 ~ 15 で、2 つ目は 15 ~ 30 です。低品質のプロファイルは、解像度が高くても同様です。Galaxy Nexus でロー プロファイルを使用すると、問題なく動作するようです。

Nexus 7 では、CamcorderProfile を調べることができず、null ポインターを取得し続けますが、これは奇妙です。4 FPS ~ 60 FPS に対応しているとのことです。動作すると思われるものを選択QUALITY_LOWすると、クラッシュし、動作するフレーム レートが見つかりません。エラーは に関連していますsetProfileが、組み込みのプロファイルに問題があると思います。確かに Android API のポイントは一貫性があることです。これはフラグシップ デバイスであり、ビデオ会議用の FF カメラがありますね?????

そのため、手動のカスタム設定を使用して 2 つのデバイスで動作させていますが、コードを使用して複数のデバイスで動作させる明確な方法がわかりません。

Nexus S は、FPS の設定に関して約束どおりに動作しないようです。Camera.getParameters().getSupportedPreviewFpsRange()

オート FPS 設定を使用できることはすべて満足ですが、どうやら FF カメラでは使用できないようです。どうすればよいですか? Nexus S で FPS を明示的に設定する必要があります。この場合、カメラが 7.5 ~ 30 FPS を処理すると言っているにもかかわらず、1 ~ 15 FPS のいずれかに設定する必要があります。

setProfile2.x ですべての問題を修正するという約束は完全には真実ではないようです。

特定の ROM 用にカメラ アプリを作成する場合、その特定のハードウェアに合わせてカスタマイズするだけなら理解できます。これが、カスタム ROM にバグのあるカメラ アプリが常にあるように見える理由を説明している可能性があります。しかし..... ダウンロード可能なビデオ録画アプリはどのように機能しますか? それらは各デバイスに合わせてカスタマイズされていますか?

これが、Facebook Poke と Twitter Vine が Android にまだない理由ですか???? :P

Google、Camera API はどうしたの?

API 15+互換性のあるすべてのデバイスの解像度とフレームレートを決定するための「ベストプラクティス」を知っている人はいますか?

それとも、テストする各デバイスでカスタム コードを記述し、残りのデバイスでサイコロを振るだけですか?

それとも、Nexus S と Nexus 7 はただの偶然なのか?

于 2013-02-06T09:38:18.243 に答える
3

フロントカメラでは QUALITY_HIGH がサポートされていないため、QUALITY_LOW で試してください。

于 2014-08-26T17:07:36.937 に答える
2

ここ数時間、-19 エラーに悩まされています。私にとっての答えは、マダバの応答、特に mCamera.unlock(); にあります。

つまり、プロファイルの設定に関する最初の回答と組み合わせて、このコード

        Camera cam = Camera.open(frontCamID);
        cam.unlock();
        recorder.setCamera(cam);

フロントカメラから選択して録画できます。

于 2014-08-28T14:21:51.110 に答える
1

ここを見る必要があります http://developer.android.com/guide/topics/media/camera.html#capture-video

そこにリストされているコマンドの順序は非常に重要です。

ここのコードの 2 番目の例を使用し ました Android でビデオ録画をキャプチャするにはどうすればよいですか?

記録開始機能を変更

protected void startRecording() throws IOException 
{
    mrec = new MediaRecorder();  // Works well

    mCamera.setPreviewDisplay(surfaceHolder);
    mCamera.startPreview();

    mCamera.unlock();
    mrec.setCamera(mCamera);

    mrec.setPreviewDisplay(surfaceHolder.getSurface());
    mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    mrec.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 

    mrec.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

    mrec.setOutputFile("/sdcard/zzzz.3gp");
    mrec.setPreviewDisplay(surfaceHolder.getSurface());

    mrec.prepare();
    mrec.start();
}
于 2013-02-04T08:56:34.447 に答える