И картинки хранят в базе и аудиофайлы, и все работает пучком, назло злопыхателям
Поиск в аудифайлах - бред сивой кобылы, этим занимаются только силовики, и то сомневаюсь, так как тут нужен мощный ASR. Обычно ищут по номеру, имени и timestamp'у, который тут же в таблицу и добавляем. Хранится это дело в blob, имеет смысл добавить mime-тип файла, src/dst номер, timestamp. Алгоритм простой :
Пример dialplan'а:
...
[macro-start-record]
exten => s,1,Set(callrecord_fname=${CALLERID(num)}-${MACRO_EXTEN}-${EPOCH}.gsm)
exten => s,n,Set(callrecord_user=${ARG1})
exten => s,n,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes)
exten => s,n,MixMonitor(${callrecord_fname},i(monitor_id))
....
exten => _1XX,Macro(start-record,${EXTEN})
same => n,Dial(SIP/${EXTEN})
exten => h,1,StopMixMonitor(${monitor_id})
exten => h,n,Agi(add_call_record.agi,${callrecord_fname},${callrecord_user})
...
Скелет AGI:
1. на входе имеем переменные callrecord_fname и callrecord_user
2. запихиваем /var/spool/asterisk/monitor/${callrecord_fname} бинарь в базу
3. удаляем нафик файл
На astxx это можно сделать в 20 строк, типа где-то так :
...
astxx::agi& agi = astxx::agi::instance();
string crf(string("/var/spool/asterisk/monitor/") + argv[1]);
ifstream cr(crf.c_str(), ios::binary);
if (!cr)
throw Exception("acr.agi: Can't open CR file " + string(argv[1]) + " !");
stringstream data;
data << cr.rdbuf();
if (!data.str().size()) {
agi.verbose("acr.agi: Hmm, zero CR file !");
unlink(crf.c_str());
exit(0);
}
agi.verbose("acr.agi: Adding callrecord : " + string(argv[1]) + ", " +
itoa(data.str().size()) + " bytes for " + string(argv[2]));
db_query q;
q << "insert into callrecords (...) values (..)";
q.execute();
unlink(crf.c_str());
...
Как наворот еще можно определять duration файла (через sox например) и добавлять его тоже - весьма удобственно рисовать это в табличке на фронтенде.