4

ケータイアプリで会話するたびにレコしたい。私のデバイスはジェイルブレイクされているので、appStore の制限については問題ありません。

もちろん、公開フレームワークは何も提供しないと思います。また、私はプライベートフレームワークを見てきましたが、有用なものは何も見ていません.

現在、マイクからの録音はできているのですが、会話が始まるとマイクが排他モードになり、データが受信されなくなります。

ガイダンスはありますか?

4

2 に答える 2

11

「Audio Recorder」は実にシンプルな調整です。作者は自分の微調整の重要な部分 (フックされている関数) を難読化しようとしましたが、ここに私が見つけたものがあります。

Tweak は基本的にAudioConverterConvertComplexBufferfromという 1 つの関数だけをフックしAudioToolbox.frameworkます。Tweak はmediaserverd起動時にデーモンにロードされます。

AudioConverterConvertComplexBufferまず、通常のオーディオ ファイルを再生しているときでも が呼び出されるため、いつ録音を開始する必要があるかを調べる必要があります。その微調整を実現するには、 からのkCTCallStatusChangeNotification通知をリッスンしCTTelephonyCenterます。

第二に、AudioConverterConvertComplexBuffer実装。まだ完成していないので、今あるものを載せておきます。これは、あなたが始めるためのいくらか実用的な例です。

AudioConverterRef と ExtAudioFileRef のペアを追跡するヘルパー クラス

@interface ConverterFile : NSObject

@property (nonatomic, assign) AudioConverterRef converter;
@property (nonatomic, assign) ExtAudioFileRef file;
@property (nonatomic, assign) BOOL failedToOpenFile;

@end

@implementation ConverterFile
@end

ConverterFile オブジェクト コンテナ

NSMutableArray* callConvertersFiles = [[NSMutableArray alloc] init];

AudioConvertConvertComplexBuffer 独自の実装

OSStatus(*AudioConverterConvertComplexBuffer_orig)(AudioConverterRef, UInt32, const AudioBufferList*, AudioBufferList*);

AudioConvertConvertComplexBuffer フック宣言

OSStatus AudioConverterConvertComplexBuffer_hook(AudioConverterRef inAudioConverter, UInt32 inNumberPCMFrames, const AudioBufferList *inInputData, AudioBufferList *outOutputData);

フッキング

MSHookFunction(AudioConverterConvertComplexBuffer, AudioConverterConvertComplexBuffer_hook, &AudioConverterConvertComplexBuffer_orig);

AudioConvertConvertComplexBuffer フックの定義

OSStatus AudioConverterConvertComplexBuffer_hook(AudioConverterRef inAudioConverter, UInt32 inNumberPCMFrames, const AudioBufferList *inInputData, AudioBufferList *outOutputData)
{
    //Searching for existing AudioConverterRef-ExtAudioFileRef pair
    __block ConverterFile* cf = nil;
    [callConvertersFiles enumerateObjectsUsingBlock:^(ConverterFile* obj, NSUInteger idx, BOOL *stop){
        if (obj.converter == inAudioConverter)
        {
            cf = obj;
            *stop = YES;
        }
    }];

    //Inserting new AudioConverterRef
    if (!cf)
    {
        cf = [[[ConverterFile alloc] init] autorelease];
        cf.converter = inAudioConverter;
        [callConvertersFiles addObject:cf];
    }

    //Opening new audio file
    if (!cf.file && !cf.failedToOpenFile)
    {
        //Obtaining input audio format
        AudioStreamBasicDescription desc;
        UInt32 descSize = sizeof(desc);
        AudioConverterGetProperty(cf.converter, kAudioConverterCurrentInputStreamDescription, &descSize, &desc);

        //Opening audio file
        CFURLRef url = CFURLCreateWithFileSystemPath(NULL, (CFStringRef)[NSString stringWithFormat:@"/var/mobile/Media/DCIM/Call%u.caf", [callConvertersFiles indexOfObject:cf]], kCFURLPOSIXPathStyle, false);
        ExtAudioFileRef audioFile = NULL;
        OSStatus result = ExtAudioFileCreateWithURL(url, kAudioFileCAFType, &desc, NULL, kAudioFileFlags_EraseFile, &audioFile);
        if (result != 0)
        {
            cf.failedToOpenFile = YES;
            cf.file = NULL;
        }
        else
        {
            cf.failedToOpenFile = NO;
            cf.file = audioFile;

            //Writing audio format
            ExtAudioFileSetProperty(cf.file, kExtAudioFileProperty_ClientDataFormat, sizeof(desc), &desc);
        }
        CFRelease(url);
    }

    //Writing audio buffer
    if (cf.file)
    {
        ExtAudioFileWrite(cf.file, inNumberPCMFrames, inInputData);
    }

    return AudioConverterConvertComplexBuffer_orig(inAudioConverter, inNumberPCMFrames, inInputData, outOutputData);
}

これは、微調整で行われるおおよその方法です。しかし、なぜそれがそのように行われるのですか?通話中の場合AudioConverterConvertComplexBuffer_hook連続して呼び出されます。ただし、inAudioConverter 引数は異なります。1 回の通話中に 9 つ以上の異なる inAudioConverter オブジェクトがフックに渡される可能性があることがわかりました。オーディオ形式が異なるため、すべてを 1 つのファイルに書き込むことはできません。これが、AudioConverterRef-ExtAudioFileRef ペアの配列を作成する理由です。何がどこに保存されているかを追跡します。このコードは、AudioConverterRef オブジェクトと同じ数のファイルを作成します。すべてのファイルには異なるオーディオが含まれます。1 つまたは 2 つがスピーカー サウンドになります。その他 - マイク。iOS 6.1 を搭載した iPhone 4S でこのコードをテストしたところ、動作しました。残念ながら、4S での通話録音は、スピーカーがオンになっている場合にのみ実行できます。iPhone 5 ではそのような制限はありません。これは tweak の説明に記載されています。

あとは、スピーカー オーディオ用とマイク用の 2 つの特定の inAudioConverter オブジェクトを見つける方法を見つけるだけです。他のすべては問題ではありません。

最後にもう 1 つ -mediaserverdプロセスはサンドボックス化されているため、微調整を行っています。必要な場所にファイルを保存できません。これが、そのファイル パスを選択した理由です。サンドボックス内からでも書き込むことができます。

PS このコードを投稿しましたが、クレジットは Elias Limneos に帰属します。彼はそれをやった。

于 2013-10-16T20:36:42.187 に答える