iOS 音频转码.mp4转.m4a、.m4a转.caf、.caf
2020-09-03 本文已影响0人
羽裳有涯
前言
iOS 有固有的音频格式,不支持mp3,转码借助三方lame库,
.mp4转.m4a 视频分类音频
+(void)accessAudioFromVideo:(NSURL *)videoPath completion:(void (^)(NSURL *outputPath,BOOL isSucceed)) completionHandle{
AVAsset *videoAsset = [AVAsset assetWithURL:videoPath];
//1创建一个AVMutableComposition
AVMutableComposition *mixComposition = [[AVMutableComposition alloc]init];
//2 创建一个轨道,类型为AVMediaTypeAudio
AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
//获取videoPath的音频插入轨道
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];
//4创建输出路径
NSString *path = [self getPathm4a];
NSURL *outputURL = [NSURL fileURLWithPath:path];
//5创建输出对象
AVAssetExportSession *exporter = [[AVAssetExportSession alloc]initWithAsset:mixComposition presetName:AVAssetExportPresetAppleM4A];
exporter.outputURL = outputURL ;
exporter.outputFileType = AVFileTypeAppleM4A;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
if (exporter.status == AVAssetExportSessionStatusCompleted) {
NSURL *outputURL = exporter.outputURL;
completionHandle(outputURL,YES);
}else {
NSLog(@"失败%@",exporter.error.description);
completionHandle(outputURL,NO);
}
}];
}
+ (NSString *)getPathm4a{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"YYYYMMdd"];
NSString *dateStr = [formatter stringFromDate:[NSDate date]];
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.m4a", dateStr]];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSError *error;
if ([[NSFileManager defaultManager] removeItemAtPath:path error:&error] == NO) {
}
}
return path;
}
m4a 转 caf 音频间转码
/**
把.m4a转为.caf格式
@param originalUrlStr .m4a文件路径
@param destUrlStr .caf文件路径
@param completed 转化完成的block
*/
+ (void)convetM4aToWav:(NSString *)originalUrlStr
destUrl:(NSString *)destUrlStr
completed:(void (^)(NSError *error)) completed {
if ([[NSFileManager defaultManager] fileExistsAtPath:destUrlStr]) {
[[NSFileManager defaultManager] removeItemAtPath:destUrlStr error:nil];
}
NSURL *originalUrl = [NSURL fileURLWithPath:originalUrlStr];
NSURL *destUrl = [NSURL fileURLWithPath:destUrlStr];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:originalUrl options:nil];
//读取原始文件信息
NSError *error = nil;
AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:songAsset error:&error];
if (error) {
NSLog (@"error: %@", error);
completed(error);
return;
}
AVAssetReaderOutput *assetReaderOutput = [AVAssetReaderAudioMixOutput
assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks
audioSettings: nil];
if (![assetReader canAddOutput:assetReaderOutput]) {
NSLog (@"can't add reader output... die!");
completed(error);
return;
}
[assetReader addOutput:assetReaderOutput];
AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:destUrl
fileType:AVFileTypeCoreAudioFormat
error:&error];
if (error) {
NSLog(@"error: %@", error);
completed(error);
return;
}
AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:11025.0], AVSampleRateKey,
[NSNumber numberWithInt:2], AVNumberOfChannelsKey,
[NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
nil];
AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
outputSettings:outputSettings];
if ([assetWriter canAddInput:assetWriterInput]) {
[assetWriter addInput:assetWriterInput];
} else {
NSLog (@"can't add asset writer input... die!");
completed(error);
return;
}
assetWriterInput.expectsMediaDataInRealTime = NO;
[assetWriter startWriting];
[assetReader startReading];
AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0];
CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale);
[assetWriter startSessionAtSourceTime:startTime];
__block UInt64 convertedByteCount = 0;
dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
[assetWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue
usingBlock: ^
{
while (assetWriterInput.readyForMoreMediaData) {
CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer];
if (nextBuffer) {
// append buffer
[assetWriterInput appendSampleBuffer: nextBuffer];
NSLog (@"appended a buffer (%zu bytes)",
CMSampleBufferGetTotalSampleSize (nextBuffer));
convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);
} else {
[assetWriterInput markAsFinished];
[assetWriter finishWritingWithCompletionHandler:^{
}];
[assetReader cancelReading];
NSDictionary *outputFileAttributes = [[NSFileManager defaultManager]
attributesOfItemAtPath:[destUrl path]
error:nil];
NSLog (@"FlyElephant %lld",[outputFileAttributes fileSize]);
break;
}
}
NSLog(@"转换结束");
// 删除临时temprecordAudio.m4a文件
NSError *removeError = nil;
if ([[NSFileManager defaultManager] fileExistsAtPath:originalUrlStr]) {
BOOL success = [[NSFileManager defaultManager] removeItemAtPath:originalUrlStr error:&removeError];
if (!success) {
NSLog(@"删除临时temprecordAudio.m4a文件失败:%@",removeError);
completed(removeError);
}else{
NSLog(@"删除临时temprecordAudio.m4a文件:%@成功",originalUrlStr);
completed(removeError);
}
}
}];
}
苹果的各种音频格式转mp3 包括各种音频格式互转
GZZAudioConverter *converter = [[GZZAudioConverter alloc] init];
converter.inputFile = m4pPath;
converter.outputFile = mp3Path;
converter.outputFileType = kAudioFileMP3Type;
converter.outputFormatID = kAudioFormatMPEGLayer3;
BOOL success = [converter convert];
dispatch_async(dispatch_get_main_queue(), ^ {
if (success) {
NSLog(@"转换成功");
} else {
NSLog(@"转换失败");
}
});
等空了做成pod 私有库,太累了 先不弄了
demo下载地址
https://gitee.com/zbc101/recorder-audio-or-video.git