Which audio format is small in size for speech recording in ios? The quality is need not to be the best but it should be understandable what user speaks.
Assuming you plan to use AVAudioRecorder class, you should provide the recording settings like so -
NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:AVAudioQualityMin], AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16], AVEncoderBitRateKey,
[NSNumber numberWithInt: 2],AVNumberOfChannelsKey,
[NSNumber numberWithFloat:44100.0], AVSampleRateKey,nil];
NSError* error = nil;
AVAudioRecorder audioRecorder = [[AVAudioRecorder alloc]
initWithURL:soundFileURL
settings:recordSettings
error:&error];
Apple's documentation provides details about the settings constants (specifically AVEncoderAudioQualityKey) you could use in your app.
22.05KHz in mono is more than adequate for speech and is 1/4 the size of 44.1KHz in stereo at the same bit depth. You could likely even try dropping it down to 11.025KHz.
Several iOS apps use the Speex encoder for lower-bit rate speech. It's not built-in, but open source source code is available to do the encoding.
Related
How can I record only one second audio sound without using file system and convert it to a byte array to send it by JSON?
NSDictionary *recordSettings = [NSDictionary
dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:AVAudioQualityMin],
AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16],
AVEncoderBitRateKey,
[NSNumber numberWithInt: 1],
AVNumberOfChannelsKey,
[NSNumber numberWithFloat:16000.0], AVSampleRateKey,
[NSNumber numberWithInt:8], AVLinearPCMBitDepthKey,
nil];
recorder = [[AVAudioRecorder alloc] initWithURL:recordedFile settings:recordSettings error:nil];
Else, I wanna know how size is this one second sound recorded and time.
Sample rate = 16,000 Hz (samples per second)
Bit rate = 16 (bits per sample)
Therefore size of 1 second sample = 16K x 16 = 256Kbits
To record one second, you can use
- (BOOL)recordForDuration:(NSTimeInterval)duration
If you want a fast start, you can prime the recording beforehand using
- (void)prepareToRecord
For recording at a specific time, use
- (BOOL)recordAtTime:(NSTimeInterval)time
forDuration:(NSTimeInterval)duration
(which implicitly calls prepareToRecord)
To get an accurate time of recording you will need to use a lower-level API. If you are not worried about accuracy, you can log the time you call the above method or the time it is written to the filesystem.
If you don't want to use the filesystem then you will need to use a lower-level API where you can get at the bitstream using a callback. Apple's Core Audio, or one of the many C++ audio engines (e.g. PortAudio, FMod, Novocaine) will let you do this.
I want to get playing audio recordings from iOS on WP8 and vice-versa.
On iOS I'm using AVAudioRecorder for that purpose with the following configuration:
NSString *tempPath = NSTemporaryDirectory();
NSURL *soundFileURL = [NSURL fileURLWithPath:[tempPath stringByAppendingPathComponent:#"sound.aac"]];
NSDictionary *recordSettings = [NSDictionary
dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatMPEG4AAC],
AVFormatIDKey,
[NSNumber numberWithInt:AVAudioQualityMin],
AVEncoderAudioQualityKey,
[NSNumber numberWithInt:8000],
AVEncoderBitRateKey,
[NSNumber numberWithInt: 1],
AVNumberOfChannelsKey,
[NSNumber numberWithFloat:8000.0],
AVSampleRateKey,
[NSNumber numberWithInt:16],
AVEncoderBitDepthHintKey,
nil];
NSError *error = nil;
_audioRecorder = [[AVAudioRecorder alloc]
initWithURL:soundFileURL
settings:recordSettings
error:&error];
_audioRecorder.delegate = self;
The files "sound.aac" contains the recording in the AAC container and playing recorded audio sample works well on iOS.
I couldn't play the "sound.aac" on WP8 after transfering the file to the WP8 device. According the following link: http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff462087(v=vs.105).aspx#BKMK_AudioSupport WP8 should be able to play the file.
The code on WP8 I've used is:
try
{
this.mediaPlayer = new MediaElement();
mediaPlayer.MediaEnded += new RoutedEventHandler(mediaPlayer_MediaEnded);
IsolatedStorageFile myStore = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream mediaStream = myStore.OpenFile("sound.aac", FileMode.Open, FileAccess.Read);
this.mediaPlayer.SetSource(mediaStream);
this.messageTextBlock.Text = "Playing the message...";
mediaPlayer.Play();
}
catch (Exception exception)
{
MessageBox.Show("Error playing audio!");
Debug.WriteLine(exception);
return;
}
After this the "sound.aac" is playing endlessly with no sound coming from speaker. The message "Playing the message..." is shown, there is no thrown Exception, no mediaPlayer_MediaEnded call. All I can do is to stop the playing.
I don't know how to get it working.
I make a FFMPEG-based player for ios. It works fine on simulator, but on real-device (iPhone 4) the frame rate is low and make my audio and video out of sync. the player works fine on iPhone 4s, so I guess it's just problem about device's computing power.
So, is there anyway to build FFMPEG optimized for iOS device (armv7, arvm7s arch)? or is there anyway to utilize ios device hardware to decode video stream?
My video stream is encode in H264/AAC.
Those streams should play just fine, I assume since your using ffmpeg you are not using a video protocol that iOS supports directly.
We use ffmpeg to do rtsp/rtmp and we get good performance with h264/aac
There are a number of factors that contribute to av/sync issues, usually some type of pre-buffering of the video is required, also network plays a big part in it.
As to your second question, hardware encoding is only available via avfoundation, you can use avassetwriter to encode your video, but again depends wether or not you need real-time.
see this link https://github.com/mooncatventures-group/FFPlayer-beta1/blob/master/FFAVFrames-test/ViewController.m
-(void) startRecording {
// // create the AVComposition
// [mutableComposition release];
// mutableComposition = [[AVMutableComposition alloc] init];
movieURL = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/%llu.mov", NSTemporaryDirectory(), mach_absolute_time()]];
NSError *movieError = nil;
assetWriter = [[AVAssetWriter alloc] initWithURL:movieURL
fileType: AVFileTypeQuickTimeMovie
error: &movieError];
NSDictionary *assetWriterInputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:FRAME_WIDTH], AVVideoWidthKey,
[NSNumber numberWithInt:FRAME_HEIGHT], AVVideoHeightKey,
nil];
assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeVideo
outputSettings:assetWriterInputSettings];
assetWriterInput.expectsMediaDataInRealTime = YES;
[assetWriter addInput:assetWriterInput];
assetWriterPixelBufferAdaptor = [[AVAssetWriterInputPixelBufferAdaptor alloc]
initWithAssetWriterInput:assetWriterInput
sourcePixelBufferAttributes:nil];
[assetWriter startWriting];
firstFrameWallClockTime = CFAbsoluteTimeGetCurrent();
[assetWriter startSessionAtSourceTime:kCMTimeZero];
startSampleing=YES;
}
The one drawback right now is that a way needs to be determined to read the encoded data as its being written, believe me when I say there are a few of us developers trying to figure out how to do that as we I write this.
I've got a live app with an estimated 15% of users reporting that the record feature is not working. This isn't happening on our test devices, but the reports show that the problem is that prepareToRecord is returning NO. I've had trouble finding sample settings for AAC format. Are any of my settings off? App requires iOS5 and uses ARC.
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithFloat:44100.0], AVSampleRateKey,
[NSNumber numberWithInt:1], AVNumberOfChannelsKey,
[NSNumber numberWithInt:AVAudioQualityHigh], AVSampleRateConverterAudioQualityKey,
[NSNumber numberWithInt:128000], AVEncoderBitRateKey,
[NSNumber numberWithInt:16], AVEncoderBitDepthHintKey,
nil];
NSString *fileName = [NSString stringWithFormat:#"%#%#.caf", verseGUID, bRecordingReference ? #"_ref" : #""];
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/%#", [[Utilities sharedInstance] documentsDirectoryPath], fileName]];
NSError *error = nil;
audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:&error];
if([audioRecorder prepareToRecord]){
[audioRecorder record];
}else{
int errorCode = CFSwapInt32HostToBig([error code]);
NSLog(#"Error: %# [%4.4s])", [error localizedDescription], (char*)&errorCode);
}
it could be many things not having to do with the recording settings.
the real question you want answered seems to be: what would cause the recording not to occur?
audioRecorder could be nil or audioRecorder prepareToPlay could be returning NO. the former seems more likely.
the url passed to initWithURL could be malformed:
- have you tested by playing with the verseGUID, bRecordReference values? maybe your devices never have a bad verseGUID, but the devices on which no recording happens have a nil/empty verseGUID. this could cause the filename to be simply ".caf".
you seem to have your own class method [Utilities sharedInstance] . could this work for some reason on your devices but not on the failing devices? if so, you could be asking to record in a top level directory when you did not mean to.
can you get the testers you have onto a "beta" list? sign up for something like TestFlight or Hockey Kit, get one or more of the users with a failure to record to also sign up, and then upload a beta of your app with diagnostics that put a dialog on screen with the resultant "error". that might be most obvious. i use testflightapp.com only because it was the first i tried, it was pretty easy for me to manage and pretty painless for my beta testers.
Try this settings which i used to record MPEG 4 AAC format...Its working good..
NSString *tempDir = NSTemporaryDirectory();
NSString *soundFilePath = [tempDir stringByAppendingPathComponent:#"sound.m4a"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithInt:AVAudioQualityMin], AVEncoderAudioQualityKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithFloat:8000.0], AVSampleRateKey,
nil];
Apologies that this is slightly tangential but I've just had a very similar issue with a number of users not being able to record, which I thought was related to audio settings.
However for me it turned out that they had denied permission to access the microphone. This meant that prepareToRecord was working (and truncating the file) and record was reporting that it was working, but actually it wasn't recording anything.
And I used this when I want to record:
AVAudioSession.sharedInstance().requestRecordPermission({(granted: Bool)-> Void in
if granted {
// can record - create AVAudioRecorder here
} else {
// can't record - update UI (or react accordingly)
}
})
Hope it saves someone some time if they run into a similar issue.
I am a newbie in AVFoundation and decoding process.I need to decode a h264 video file and play it in iphone...can anyone give me guideline to do it.
I dont want to use ffmpeg or any third party library to do that. As far as I know using Avfoundation encoding is possible...here is the code which I thought is used for encoding but not sure at all...
float bitsPerPixel;
CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(currentFormatDescription);
int numPixels = dimensions.width * dimensions.height;
int bitsPerSecond;
// Assume that lower-than-SD resolutions are intended for streaming, and use a lower bitrate
if ( numPixels < (640 * 480) )
bitsPerPixel = 4.05; // This bitrate matches the quality produced by AVCaptureSessionPresetMedium or Low.
else
bitsPerPixel = 11.4; // This bitrate matches the quality produced by AVCaptureSessionPresetHigh.
bitsPerSecond = numPixels * bitsPerPixel;
NSDictionary *videoCompressionSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInteger:dimensions.width], AVVideoWidthKey,
[NSNumber numberWithInteger:dimensions.height], AVVideoHeightKey,
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger:bitsPerSecond], AVVideoAverageBitRateKey,
[NSNumber numberWithInteger:30], AVVideoMaxKeyFrameIntervalKey,
nil], AVVideoCompressionPropertiesKey,
nil];
if ([assetWriter canApplyOutputSettings:videoCompressionSettings forMediaType:AVMediaTypeVideo]) {
assetWriterVideoIn = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:videoCompressionSettings];
assetWriterVideoIn.expectsMediaDataInRealTime = YES;
assetWriterVideoIn.transform = [self transformFromCurrentVideoOrientationToOrientation:self.referenceOrientation];
if ([assetWriter canAddInput:assetWriterVideoIn])
[assetWriter addInput:assetWriterVideoIn];
else {
NSLog(#"Couldn't add asset writer video input.");
return NO;
}
}
else {
NSLog(#"Couldn't apply video output settings.");
return NO;
}
return YES;
I am completely naive about this, please help...from where to start///
thanks
The simpler solution is to use MPMoviePlayerController. It takes in input a mov or mv4 file (from local file system or through an URL).
The another option is to use AVPlayer class.
Hope it helps,
David
You can refer and build the official sample code: AVPlayerDemo to see how it works. It uses AV Foundation framework, mainly the AVPlayer APIs to play video files and the performance is excellent.
To play a video file by AVPlayerDemo you should copy the video files to your iOS device by itunes and select iPod library on the AVPlayerDemo App.