I'm trying to control the bit depth of a .m4a file recorded with AVRecorder :
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: 8], AVEncoderBitDepthHintKey,
nil];
But AVEncoderBitDepthHintKey has no effect, same for AVEncoderAudioQualityKey.
It seems that iOS7 and 8 have different defaults : iOS7 always gives a s16p format (according to ffmpeg) and iOS8 a s32p.
I don't want to use any other format than AppleLossless.
I don't think AVEncoderAudioQualityKey is applicable to kAudioFormatAppleLossless and AVEncoderBitDepthHintKey is only a hint.
Maybe you'd have more luck getting 8bit audio in ALAC via the lower level CoreAudio AudioConverter API.
Related
I'm attempting to use the AVAssetWriterInput to crop a video that I read in a screencast of my application. Here is my current configuration.
NSDictionary *videoCleanApertureSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:320], AVVideoCleanApertureWidthKey,
[NSNumber numberWithInt:480], AVVideoCleanApertureHeightKey,
[NSNumber numberWithInt:10], AVVideoCleanApertureHorizontalOffsetKey,
[NSNumber numberWithInt:10], AVVideoCleanApertureVerticalOffsetKey,
nil];
NSDictionary *videoAspectRatioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:3], AVVideoPixelAspectRatioHorizontalSpacingKey,
[NSNumber numberWithInt:3],AVVideoPixelAspectRatioVerticalSpacingKey,
nil];
NSDictionary *codecSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:960000], AVVideoAverageBitRateKey,
[NSNumber numberWithInt:1],AVVideoMaxKeyFrameIntervalKey,
videoCleanApertureSettings, AVVideoCleanApertureKey,
videoAspectRatioSettings, AVVideoPixelAspectRatioKey,
AVVideoProfileLevelH264BaselineAutoLevel, AVVideoProfileLevelKey,
nil];
NSDictionary *videoSettings = #{AVVideoCodecKey:AVVideoCodecH264,
AVVideoCompressionPropertiesKey:codecSettings,
AVVideoScalingModeKey:AVVideoScalingModeResizeAspectFill,
AVVideoWidthKey:[NSNumber numberWithInt:320],
AVVideoHeightKey:[NSNumber numberWithInt:480]};
_videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
I'm receiving the following error: "AVAssetWriterInput does not currently support AVVideoScalingModeFit"
This is a common error for anyone using this library, but I can't find the actual solution to it. I just see people saying: "I figured it out eventually" without explaining it. The problem is definitely related to this line: "AVVideoScalingModeKey:AVVideoScalingModeResizeAspectFill," which tells the AVAssetWriter to crop the video and maintain the aspect ratio. Anyone know the solution to this?
There is no "solution to it" per se. It's simply unsupported. You'll need to scale the video frames yourself using Core Image or a VTPixelTransferSession or whatever is appropriate for your pipeline.
My code worked fine until iOS 8 kAudioFormatMPEG4AAC but now it creates an empty file. No errors are reported. When I changed it to kAudioFormatLinearPCM it works. This is my code:
recordSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:AVAudioQualityMin], AVEncoderAudioQualityKey,
[NSNumber numberWithInt: kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithInt:16], AVEncoderBitRateKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithFloat:32000.0], AVSampleRateKey,
nil];
Please remove AVEncoderBitRateKey key from your settings dictionary and it will work on iOS8 with kAudioFormatMPEG4AAC.
It could be a specific correlation between AVEncoderBitRateKey and AVNumberOfChannelsKey. But I didn't play with parameters but used default bitrate value to get working recorder.
That bitrate looks suspiciously low, even for kAudioFormatMPEG4AAC (16 bytes per second), maybe try 16000 or 64000 or more.
p.s. try the new Objective-C literals for your NSDictionarys, NSArrays and NSNumbers, I think they're an improvement:
recordSettings = #{
AVEncoderAudioQualityKey : AVAudioQualityMin,
AVFormatIDKey : #(kAudioFormatLinearPCM),
AVEncoderBitRateKey : #16000,
AVNumberOfChannelsKey : #1,
AVSampleRateKey : #32000
};
I'm using AVAssetWriter to output wav file in the app temp folder with these settings:
NSDictionary* outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[ NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
[ NSNumber numberWithInt: 2 ], AVNumberOfChannelsKey,
[ NSNumber numberWithFloat: 44100.0 ], AVSampleRateKey,
[ NSData data ], AVChannelLayoutKey,
[ NSNumber numberWithInt: 64000 ], AVEncoderBitRateKey,
nil];
It's outputting seemingly normal 45mb .wav file but the app can not read it anyways. I suspect the file header is corrupt because I opened the the .wav in audacity (which accepted it no problem) and re-exported it with again .wav extension. The exported file worked fine in the app.
I also opened the both .wav files with the text editor to see the headers and they were somewhat different.
any clues?
You're using kAudioFormatMPEG4AAC for AVFormatIDKey when you should be using kAudioFormatLinearPCM. Wave files are a PCM format and cannot be exported with MPEG-4 packets.
Scenario: The App which I am working on I am suppose to recored voice memos and send them to the Windows client. Recording audio in iOS is not that much hard but the recorded file (in my case in the form of .mp3) could not be playable in Windows but the same file could be easily playable in Mac.
I strongly suspect on my audio recording settings which I am using in the following code,
_audioRecorder = [[AVAudioRecorder alloc] initWithURL:audioFileURL settings:_recordingSettings error:&error];
and the settings that I am using is,
_recordingSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithInt:AVAudioQualityMin], AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16], AVEncoderBitRateKey,
[NSNumber numberWithInt: 2], AVNumberOfChannelsKey,
[NSNumber numberWithFloat:44100.0], AVSampleRateKey,
nil];
I have already tried the various AVFormatIDKeys such as
kAudioFormatLinearPCM - .lpcm
kAudioFormatMPEG4AAC - .acc
kAudioFormatMPEGLayer3 - .mp3
but no gain.
I appreciate any help. In case if it is not possible I need the explanation why!
After some random tries I have managed myself with the settings,
_recordingSettings = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
[NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsNonInterleaved,
[NSNumber numberWithInt:AVAudioQualityMin], AVEncoderAudioQualityKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithFloat:2000.0], AVSampleRateKey,
nil];
Important: The filename should be "someName.wav"
Is there any way to convert my recorded .WAV file to .M4A file in iOS?
And also I have to convert .M4A file to .WAV file.
I tried with Audio Queue Services, but I am not able to do.
This post: From iPod Library to PCM Samples in Far Fewer Steps Than Were Previously Necessary describes how to load a file from the users ipod library and write it to the file system as a linear pcm (wav) file.
I believe that the change that you will need to make to the code to load a file from the file system instead would be in the NSURL that describes where the asset is:
-(IBAction) convertTapped: (id) sender {
// set up an AVAssetReader to read from the iPod Library
NSURL *assetURL = [[NSURL alloc] initFileURLWithPath:#"your_m4a.m4a"];
AVURLAsset *songAsset =
[AVURLAsset URLAssetWithURL:assetURL options:nil];
NSError *assetError = nil;
AVAssetReader *assetReader =
[[AVAssetReader assetReaderWithAsset:songAsset
error:&assetError]
retain];
if (assetError) {
NSLog (#"error: %#", assetError);
return;
}
If you are going in the opposite direction, you will need to change the formatting on the output end:
NSDictionary *outputSettings =[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:44100.0], AVSampleRateKey,
[NSNumber numberWithInt:2], AVNumberOfChannelsKey,
[NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)],
AVChannelLayoutKey,
[NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
nil];
I am not sure of the exact settings that would go in here for m4a, but this should get you closer.
The other option would be to load in ffmpeg lib and do all your conversion in there, but that seems like different than what you want.
TPAACAudioConverter works fine