Androidでカメラのシャッター音を消したアプリの作り方のメモ
Androidでカメラのシャッター音を消したアプリの作り方のメモです。
カメラアプリを作る際に、
private ShutterCallback _fnShutterCallback = new ShutterCallback();
private final class ShutterCallback implements android.hardware.Camera.ShutterCallback
{
public void onShutter()
{
Log.i("camera", "onShutter");
if (_cMediaShutterSound != null)
{
// _cMediaShutterSound.start();
}
}
};
というように、シャッター音がならないコールバック関数を用意して撮影時に、
camera.takePicture(_fnShutterCallback,_fnRawPictureCallback,new JpegPictureCallback());というようにシャッターコールバックを呼べばシャッター音が無音のカメラアプリが作れるはず、、、なのに、実際にはシャッター音が鳴る。しかもコメント部分をはずせばシャッター音が二重に鳴るというおまけ付き。
Android OSのソースコードをざっと調べてみると、
source/frameworks/base/camera/libcameraservice/CameraService.cpp
の中に実装されているシャッターハンドラーが
// snapshot taken
void CameraService::Client::handleShutter(
image_rect_type *size // The width and height of yuv picture for
// registerBuffer. If this is NULL, use the picture
// size from parameters.
)
{
// Play shutter sound.
if (mMediaPlayerClick.get() != NULL) {
// do not play shutter sound if stream volume is 0
// (typically because ringer mode is silent).
int index;
AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
if (index != 0) {
mMediaPlayerClick->seekTo(0);
mMediaPlayerClick->start();
}
}
//以下省略
というようになっていて、強制的に音がようになっている。シャッター音を消すオプションは存在せず、mMediaPlayerClickが失敗した場合のみ無音になる。
以上の理由から「シャッター音が鳴らないAndroidアプリは作れない」、、、はずだが実際には数多くの無音カメラアプリがリリースされているためできるはず。
というわけで、カメラのシャッター音を消す方法は、、、
■CameraService.cppで参照されているシャッター音のリソースファイルを無音にする
■シャッター音が鳴ってしまうcamera.takePicture()を使わずに撮影する
■ソースコードのシャッター音を鳴らす部分をコメントアウトしたlibcameraserviceをビルドして使う
■/dev/video1や/dev/msm_cameraなどのカメラデバイスを直接制御して撮影する
という4方法をすぐに思いつく。
「CameraService.cppで参照されているシャッター音のリソースファイルを無音にする」は、シャッター音の元ファイル"/system/media/audio/ui/camera_click.ogg"を無音のものに置き換えるというもの。
検索すれば情報もたくさんあるので簡単にシャッター音を無音にできる。ただしroot権限が必要になるため汎用的ではない。
「シャッター音が鳴ってしまうcamera.takePicture()を使わずに撮影する」は、例えばプレビュー用に生成された画像イメージを取得してそのまま撮影データとして利用するというもの。
簡単に実装できて、汎用的なシャッター音を消したカメラアプリを作成できる。この方法ではcamera.takePicture()を使った撮影とは異なり、ラグがなくプレビューを見たまま撮影できるためサクサク撮影可能というメリットがある。ただしプレビュー画像はcamera.takePicture()での画像よりも解像度が低いため、高解像度で撮影したい場合はこの方法は利用できない。
「ソースコードのシャッター音を鳴らす部分をコメントアウトしたlibcameraserviceをビルドして使う」は、Androidのソースコードをほぼそのまま利用するもの。
実際に試していないので、本当に無音化できるかどうかは不明。しかし、おそらくリリースされているカメラアプリはこの方法を利用して無音化しているはず。
「/dev/video1や/dev/msm_cameraなどのカメラデバイスを直接制御して撮影する」は、Androidという枠から抜け出てLinuxとしてカメラを扱うというもの。
試していないので、本当に直接制御できるのかは不明。また、デバイスに直接アクセスするため機種依存性が強くなるというデメリットもある。NDKが標準でlinux/videodev2.hを備えているなど、ハードルが高いようで低いように思える。
、、、ものの単純に「int fd = open("/dev/msm_camera",O_RDWR,0);」としてもデバイスが開けず難航しそうな雰囲気。/dev/msm_cameraがAndroid側で利用中なため開放作業やパーミッション変更などの前処理が必要になるのかな?デバイスが開けたら後は簡単にできそう。この方法はAndroid OSが用意しているカメラAPIとは異なり自由度が高い。そのため今後なんとかして動かせるようにしたい。現状ではAndroidもLinuxも知識がゼロに等しいので歯が立ちません。

