Случайное повреждение файла при использовании AVAudioRecorder (иногда файл не может быть воспроизведен) - iOS

В приложении, которое я сейчас разрабатываю, я более или менее уперся в кирпичную стену. В приложении вы можете войти в представление, в котором перечислены все локально сохраненные аудиофайлы в стандартном табличном представлении. Отсюда вы можете нажать на них, чтобы воспроизвести их, или нажать кнопку записи ниже, чтобы сделать новую запись, которая впоследствии будет автоматически сохранена в песочнице приложения.

Теперь все это действительно работает отлично большую часть времени. Я могу сидеть, делать записи и воспроизводить их. Я могу сидеть и тестировать это снова и снова около 45 без каких-либо проблем. Затем внезапно в случайное время я наталкиваюсь на очень странную проблему. Проблема в том, что диктофон внезапно начинает сохранять только поврежденные файлы, которые не могут быть воспроизведены и имеют размер ровно 4096 байт, независимо от того, как долго вы записываете.

Я использую AVAudioRecorder совершенно стандартным образом, настраивая его так:

// Specific settings for the audio recording
NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithInt:AVAudioQualityMin],
    AVEncoderAudioQualityKey,
    [NSNumber numberWithInt:8], 
    AVEncoderBitRateKey,
    [NSNumber numberWithInt: 2], 
    AVNumberOfChannelsKey,
    [NSNumber numberWithFloat:22000.0], 
    AVSampleRateKey,
    nil];

NSError *error = nil;
audioRecorder = [[AVAudioRecorder alloc]
    initWithURL:contentURL
    settings:recordSettings
    error:&error];
audioRecorder.delegate = self;

Я начинаю запись так:

if (!isRecording) {
    isRecording = YES;
    [audioRecorder record];

    // Start the timer
    recordTiming = [NSDate date];

    timeCheck = [NSTimer
        scheduledTimerWithTimeInterval:1.0f
        target:self
        selector:@selector(timeCheck)
        userInfo:nil
        repeats:YES];
}

А затем остановив это с помощью этого:

if (isRecording) {
    [audioRecorder stop];

    // Stop the timer
    [timeCheck invalidate];
}

Я понятия не имею, что могло вызвать эту проблему. Пока что перепробовал практически все. Я проверял, правильно ли перерабатывается объект рекордера (чтобы у вас был новый экземпляр для каждой записи сейчас), и что старая ссылка освобождена и так далее, чтобы убедиться, что она не имеет ничего общего с мешающими объектами, но ничего не решает.

Есть ли кто-нибудь, кто хоть немного понимает, что может вызвать проблемы с поврежденными файлами?


person CodingBeagle    schedule 14.03.2012    source источник
comment
Итак, вы говорите, что переменная ошибки всегда равна нулю после инициализации audioRecorder, верно?   -  person A-Live    schedule 14.03.2012
comment
Да, правильно :) На самом деле у меня есть несколько быстрых проверок ошибок ниже для NSLog, чтобы убедиться, что он правильно инициализирован, а NSError равен нулю и так далее.   -  person CodingBeagle    schedule 14.03.2012
comment
Понятно, тогда давайте улучшим ваш код, проблема, вероятно, должна стать очевидной или исчезнуть. Вместо использования isRecording var вы можете использовать запись свойства audioRecorder; я не вижу инициализацию аудиосессии, но вы, вероятно, просто ее пропустили. Однако я бы посоветовал вам также улучшить обработку ошибок, ответ ниже можно использовать в качестве справки: stackoverflow.com/questions/1010343/   -  person A-Live    schedule 14.03.2012
comment
Да, сейчас я попытался улучшить обработку некоторых ошибок :) Я также сузил ошибку до момента начала записи, то есть в строке: [audioRecorder record]; Я обнаружил, что в некоторых случаях он как бы случайным образом возвращает NO. Кто-то еще посоветовал мне начать аудиосеанс перед записью. Я еще не получил ошибку, но, возможно, она все еще существует. Трудно сказать, время может быть таким случайным :) Как вы думаете, аудиосеанс может сыграть в этом свою роль? Кстати, спасибо за помощь :) Очень понравилось.   -  person CodingBeagle    schedule 14.03.2012
comment
Я должен так думать, потому что это я предложил это на ваш другой вопрос. По моему опыту   -  person A-Live    schedule 14.03.2012
comment
Я должен так думать, потому что это я предложил это на ваш другой вопрос. По моему опыту, самая сложная часть звука iOS - это подготовка одной надежной версии, которую вы будете использовать позже, поскольку доступных сэмплов не так много. Аудиосеанс - одна из важных вещей, которую следует учитывать, но это не стопроцентное решение. Критически важно выполнить все возможные проверки при работе с основным звуком, а также внимательно прочитать документацию.   -  person A-Live    schedule 15.03.2012
comment
Я видел ваш другой вопрос, и похоже, что Сессия была виновата здесь. Это правда? Я могу найти только вас, у кого возникла эта проблема. Я работаю над этим, но мой сеанс настроен на запись и активируется непосредственно перед началом записи. Что еще способствовало этому? Если я не получу ответа, я отправлю свой. Спасибо.   -  person jbcaveman    schedule 30.03.2012
comment
На самом деле, я думаю, что просто исправил это. У меня был метод prepareRecorder, который настраивал детали записи и вызывал prepareToRecord, ожидая нажатия кнопки (я видел это предложение где-то еще, предложенное, чтобы ускорить начало записи). Он работает без ошибок до сих пор после его удаления и размещения всего одним методом, например, в этом сообщении: stackoverflow.com/questions/1010343/   -  person jbcaveman    schedule 30.03.2012
comment
Извините за задержку ответа, какое-то время не проверял stackoverflow :) Но да, решение было найдено в этом вопросе: stackoverflow.com/questions/9706020/, где вы можете увидеть фрагмент кода в ответе с пометкой с зеленым. Это действительно была аудиосессия, и я должен был убедиться, что вставил фрагмент аудиосессии перед началом любой записи :) Надеюсь, это поможет прояснить ситуацию   -  person CodingBeagle    schedule 10.04.2012
comment
@ user1163640: не могли бы вы опубликовать свое решение в качестве ответа и принять его, чтобы другие тоже могли легко его найти?   -  person patric.schenke    schedule 07.03.2013


Ответы (1)


Примечание. Поскольку OP неактивен в течение нескольких дней, и я полагаю, что на этот вопрос следует ответить для дальнейшего использования, я публикую этот ответ.

Перед началом записи необходимо получить AVAudioSession.

AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
[audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err];
if(err){
   NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
   return;
}
err = nil;
[audioSession setActive:YES error:&err];
if(err){
   NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
   return;
}

Ссылка: https://stackoverflow.com/a/9706731/188331

person Raptor    schedule 08.03.2013
comment
Это действительно была проблема :) Прошло много времени с тех пор, как я проверял свои старые вопросы, поэтому извиняюсь за это, но это действительно решение проблемы. - person CodingBeagle; 11.03.2013