ラズベリーパイ防犯カメラ ~再生秒数の長い録画だけを抽出する機能を追加~

実際に玄関まで来た録画のみをリストアップ

防犯カメラ機能を実際に使っていると家の前を数秒で通り過ぎる録画が沢山出来てしまい、玄関に訪問した録画だけを抽出する機能が欲しくなりました。

調べてみると郵便受けに投函するだけの配達は20秒以上、チャイムを鳴らす配達や訪問は1分以上かかることがわかりました。時間で絞り込めばよいのではないかと考え、機能を追加しました。

時間で録画を絞り込む機能を追加

mp4ファイルの再生時間を抽出するのに、当初はffmpegを使用することを検討していましたが、このコマンドは動画ファイルの全てのプロパティをキャラクタで出力し、そこから再生時間だけを抜き出すという処理が必要になるので、1ファイルにつき0.5秒程かかります。現行の仕組みに組み込むと画面表示にかなりの時間がかかるため、再生時間だけを出力するプログラムを自作することにしました。

解析ツールの作成に当たり、以下のURLを参考にしました。
mp4のファイル構造を解説
https://qiita.com/satken2/items/d14b4113fe3fb5f5597b
NovieファイルのAtom情報を解析
https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html
mp4 mvhd 解析
http://wikil.lwwhome.cn:28080/?p=607
mp4の情報を表示するツール Header Reader MP4
https://dev.onionsoft.net/seed/info.ax?id=1303
mp4の情報を表示するツール Mp4Reader
https://github.com/suzutsuki0220/Mp4Reader

作成したプログラムmp4lenのソースは以下のようになります。
コマンド成功で戻り値に0を返し、標準出力に再生時間をmsで返します。
コメントが少なすぎますがご容赦を
main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int cnv4b2int( unsigned char* buf );

int main(int argc, char** argv){
  int ret = 1;

  if( argc < 2 ){
    return 1;
  }
  FILE* fp  = fopen( argv[1], "rb" );
  if( fp == NULL ){
    return 1;
  }

  for( int i = 0; i < 100; i++ ){
    unsigned char typeBuff[8] = { 0 };  // size(4)type(4)のバッファ
    if( fread( typeBuff, 1, 8, fp ) < 8 ){
      break;
    }
    int chklen = cnv4b2int( &typeBuff[0] );
    if( memcmp( "moov", &typeBuff[4], 4 ) == 0 ){
      for( int j = 0; j < 100; j++){
        if( fread( typeBuff, 1, 8, fp) < 8 ){
          break;
        }
        int chklen2 = cnv4b2int( &typeBuff[0] );
        if( memcmp( "mvhd", &typeBuff[4], 4 ) == 0 ){
          if( fseek( fp, 16, SEEK_CUR ) != 0 ){
            break;
          }
          if( fread( typeBuff, 1, 4, fp ) < 4 ){
            break;
          }
          printf( "%u\n", cnv4b2int( typeBuff ) );
          ret = 0;
          break;
        }
        if( fseek( fp, chklen2 - 8, SEEK_CUR ) != 0 ){
          break;
        }
      }
      break;
    } else {
      if( fseek( fp, chklen - 8, SEEK_CUR ) != 0 ){
        break;
      }
    }
  }
  fclose( fp );
  return ret;
}

int cnv4b2int( unsigned char* buf ){
  return (buf[0]*0x1000000 + buf[1]*0x10000 + buf[2]*0x100 + buf[3]);
}

mp4lenプログラムはビルドして以下の圧縮ファイルに同梱していますが、自分でビルドする場合は以下のコマンドを実行します。
$gcc main.cpp -o mp4len
実行時間は15msほどになりました。60ファイルで1秒ほどかかりちょっと時間がかかりますが、大分改善されました。

ftpアプリを使い、更新した新しいhtmlファイルの一式を/var/www/htmlに上書き転送します。
※これまでのファイルは削除しても構いません。
※「カメラ用ラズパイ・サーバーセットアップ」を参照

アップロードしたmp4lenプログラムに実行権限を付与します。
$chmod a+x /var/www/html/mp4len

これで時間で絞り込む機能が追加されます。
※ボタンがうまく表示されない場合は、chromiumブラウザのキャッシュをクリアします。

絞り込み時間を変更する場合は/func/config.iniの項目を変更します。
middle=20
long=60