我正在尝试将音频录制到文件中14天。我正在通过接收音频的屏幕镜像获取PCM格式的音频数据,并使用此代码将其转换为CMSampleBuffer
-(void)createAudioSampleBufferFromData:(uint8_t*)buf withSize:(uint32_t)buflen timeStamp:(double)timeStamp{
OSStatus status;
AudioStreamBasicDescription monoStreamFormat;
memset(&monoStreamFormat, 0, sizeof(monoStreamFormat));
monoStreamFormat.mFormatID = kAudioFormatLinearPCM;
monoStreamFormat.mSampleRate = 44100;
monoStreamFormat.mChannelsPerFrame = 2;
monoStreamFormat.mBitsPerChannel = 16;
monoStreamFormat.mFramesPerPacket = 1; // uncompressed audio
monoStreamFormat.mBytesPerFrame =monoStreamFormat.mChannelsPerFrame * monoStreamFormat.mBitsPerChannel/8;
monoStreamFormat.mBytesPerPacket = monoStreamFormat.mBytesPerFrame * monoStreamFormat.mFramesPerPacket;
monoStreamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
CMFormatDescriptionRef format = NULL;
status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &monoStreamFormat, 0, NULL, 0, NULL, NULL, &format);
if (status != noErr) {
// really shouldn't happen
return;
}
long blockLength = buflen;
CMSampleBufferRef sampleBuffer = NULL;
CMBlockBufferRef blockBuffer = NULL;
status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, buf, // memoryBlock to hold buffered data
blockLength, // block length of the mem block in bytes.
kCFAllocatorDefault, NULL,
0, // offsetToData
blockLength, // dataLength of relevant bytes, starting at offsetToData
0, &blockBuffer);
if(status == noErr)
{
CMSampleTimingInfo timings = {CMTimeMake(1, 44100.0), CMClockGetTime(CMClockGetHostTimeClock()), kCMTimeInvalid };
const size_t sampleSize = blockLength;
status = CMSampleBufferCreate(kCFAllocatorDefault,
NULL, true, NULL, NULL,
format, 1, 0, &timings, 1,
&sampleSize, &sampleBuffer);
CMItemCount itemCount = CMSampleBufferGetNumSamples(sampleBuffer);
[self notifyAudioBufferReceived:sampleBuffer];
// if(blockBuffer)
// CFRelease(blockBuffer);
}
}
在以下方法中,此CMSampleBuffers
正在接收:
- (void)airPlayServer:(id)server audioBufferReceived:(CMSampleBufferRef)buffer {
if(recordingStarted){
[decoderAndRecorder.recorder newAudioSample:buffer];
}
// CFRelease(buffer);
}
这些缓冲区从此处转到AVAssetWriter类,在该类中我将这些缓冲区附加到文件中以将音频录制到文件中。 AVAssetWriter类如下:
- (instancetype)init
{
self = [super init];
if (self) {
// Create asset writer
dateString = [self dateInString];
NSString *documents = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
filePath = [documents stringByAppendingPathComponent:[NSString stringWithFormat:@"screen recording - %@.caf",dateString]];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
[[NSFileManager defaultManager] removeItemAtPath:filePath
error:nil];
}
NSLog(@"%@", filePath);
NSError *error = nil;
_assetWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:filePath]
fileType:AVFileTypeCoreAudioFormat
error:&error];
AudioChannelLayout acl;
memset(&acl,0, sizeof(acl));
acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
NSDictionary* audioOutputSettings = nil;
audioOutputSettings = [ NSDictionary dictionaryWithObjectsAndKeys:
[ NSNumber numberWithInt: kAudioFormatLinearPCM ], AVFormatIDKey,
[ NSNumber numberWithFloat: 44100.0 ], AVSampleRateKey,
[ NSNumber numberWithInt: 1 ], AVNumberOfChannelsKey,
[ NSData dataWithBytes: &acl length: sizeof( acl ) ], AVChannelLayoutKey,
[ NSNumber numberWithInt: 16 ], AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
[NSNumber numberWithBool:NO], AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
nil ];
_audioWriterInput = [[AVAssetWriterInput alloc]
initWithMediaType: AVMediaTypeAudio
outputSettings: audioOutputSettings ];
_audioWriterInput.expectsMediaDataInRealTime = YES;
NSParameterAssert(_audioWriterInput);
NSParameterAssert([_assetWriter canAddInput:_audioWriterInput]);
[_assetWriter addInput:_audioWriterInput];
}
}
return self;
}
-(void)startSession{
//This is vedio recorder code
_isStarted =[_assetWriter startWriting];
if(_isStarted)
{
NSLog(@"======== Session started");
[_assetWriter startSessionAtSourceTime:_startingTime];
}
else {
NSLog(@"======== Session failed : %@", _assetWriter.error);
}
}
-(void)endSession
{
_isStarted = NO;
[_audioWriterInput markAsFinished];
[_assetWriter finishWritingWithCompletionHandler:^{
NSLog(@"====== File Save Successfully =======");
}];
}
- (void)newAudioSample:(CMSampleBufferRef)sampleBuffer
{
if (_isStarted) {
if (_videoWriter.status == AVAssetWriterStatusWriting) {
// if(_audioWriterInput.readyForMoreMediaData){
//NSLog(@"Warning: writer status is %d", _videoWriter.status)
if(sampleBuffer){
if (![_audioWriterInput appendSampleBuffer:sampleBuffer]) {
NSLog(@"Unable to write to audio input");
}else{
NSLog(@"====Audio is being recorded===");
}
}
// }
}else if(_videoWriter.status == AVAssetWriterStatusFailed){
NSLog(@"<----- Appending failed ----->");
NSLog(@"Error: %@", _videoWriter.error);
}
}
}
仅此而已。文件已创建,但具有零字节。没有数据写入其中。请协助解决这个问题。