ios - 将视频的音频转换为 AAC
ios - Convert video's audio to AAC
我正在尝试将任何音频格式编码为 AAC 格式,采样率为 44100Hz。
所以基本上:输入(mp3、aac?等,任何采样率)-> AAC (44100Hz)
源音频来自视频 (mp4),但我可以将其提取为 m4a (AAC)。问题是我还想将采样率更改为 44100Hz。
我正在尝试使用 AVAssetReader 和 AVAssetWriter 实现此目的,但不确定是否可行或者是否是最佳解决方案。任何其他解决方案将不胜感激!
到目前为止,这是我的代码:
// Input video audio (.mp4)
AVAsset *videoAsset = <mp4 video asset>;
NSArray<AVAssetTrack *> *videoAudioTracks = [videoAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *videoAudioTrack = [videoAudioTracks objectAtIndex:0];
// Output audio (.m4a AAC)
NSURL *exportUrl = <m4a, aac output file URL>;
// ASSET READER
NSError *error;
AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:videoAsset
error:&error];
if(error) {
NSLog(@"error:%@",error);
return;
}
// Asset reader output
AVAssetReaderOutput *assetReaderOutput =[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoAudioTrack
outputSettings:nil];
if(![assetReader canAddOutput:assetReaderOutput]) {
NSLog(@"Can't add output!");
return;
}
[assetReader addOutput:assetReaderOutput];
// ASSET WRITER
AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:exportUrl
fileType:AVFileTypeAppleM4A
error:&error];
if(error) {
NSLog(@"error:%@",error);
return;
}
AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
NSDictionary *outputSettings = @{AVFormatIDKey: @(kAudioFormatMPEG4AAC),
AVNumberOfChannelsKey: @2,
AVSampleRateKey: @44100.0F,
AVChannelLayoutKey: [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)],
AVEncoderBitRateKey: @64000};
/*NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:44100.f], 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];*/
// Asset writer input
AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
outputSettings:outputSettings];
if ([assetWriter canAddInput:assetWriterInput])
[assetWriter addInput:assetWriterInput];
else {
NSLog(@"can't add asset writer input... die!");
return;
}
assetWriterInput.expectsMediaDataInRealTime = NO;
[assetWriter startWriting];
[assetReader startReading];
CMTime startTime = CMTimeMake (0, videoAudioTrack.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];
convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);
CMSampleBufferInvalidate(nextBuffer);
CFRelease(nextBuffer);
nextBuffer = NULL;
}
else
{
[assetWriterInput markAsFinished];
// [assetWriter finishWriting];
[assetReader cancelReading];
break;
}
}
}];
这是我在包含 mp3 音轨的视频中遇到的错误:
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '*** -[AVAssetWriterInput
appendSampleBuffer:] Cannot append sample buffer: Input buffer must
be in an uncompressed format when outputSettings is not nil'
任何帮助将不胜感激,谢谢!
您应该可以通过配置 AVAssetReaderOutput
输出设置来实现此目的:
NSDictionary *readerOutputSettings = @{ AVSampleRateKey: @44100, AVFormatIDKey: @(kAudioFormatLinearPCM) };
AVAssetReaderOutput *assetReaderOutput =[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoAudioTrack
outputSettings:readerOutputSettings];
我不是 Obj-C 的本地人,我不得不 google 弄清楚 Swift 中的 。
这里是 Swift 版本:
let audioSettings: [String : Any] = [
AVFormatIDKey: kAudioFormatLinearPCM,
AVSampleRateKey: 44100
]
let assetReaderAudioOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: audioSettings)
我正在尝试将任何音频格式编码为 AAC 格式,采样率为 44100Hz。
所以基本上:输入(mp3、aac?等,任何采样率)-> AAC (44100Hz)
源音频来自视频 (mp4),但我可以将其提取为 m4a (AAC)。问题是我还想将采样率更改为 44100Hz。
我正在尝试使用 AVAssetReader 和 AVAssetWriter 实现此目的,但不确定是否可行或者是否是最佳解决方案。任何其他解决方案将不胜感激!
到目前为止,这是我的代码:
// Input video audio (.mp4)
AVAsset *videoAsset = <mp4 video asset>;
NSArray<AVAssetTrack *> *videoAudioTracks = [videoAsset tracksWithMediaType:AVMediaTypeAudio];
AVAssetTrack *videoAudioTrack = [videoAudioTracks objectAtIndex:0];
// Output audio (.m4a AAC)
NSURL *exportUrl = <m4a, aac output file URL>;
// ASSET READER
NSError *error;
AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:videoAsset
error:&error];
if(error) {
NSLog(@"error:%@",error);
return;
}
// Asset reader output
AVAssetReaderOutput *assetReaderOutput =[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoAudioTrack
outputSettings:nil];
if(![assetReader canAddOutput:assetReaderOutput]) {
NSLog(@"Can't add output!");
return;
}
[assetReader addOutput:assetReaderOutput];
// ASSET WRITER
AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:exportUrl
fileType:AVFileTypeAppleM4A
error:&error];
if(error) {
NSLog(@"error:%@",error);
return;
}
AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
NSDictionary *outputSettings = @{AVFormatIDKey: @(kAudioFormatMPEG4AAC),
AVNumberOfChannelsKey: @2,
AVSampleRateKey: @44100.0F,
AVChannelLayoutKey: [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)],
AVEncoderBitRateKey: @64000};
/*NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:44100.f], 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];*/
// Asset writer input
AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
outputSettings:outputSettings];
if ([assetWriter canAddInput:assetWriterInput])
[assetWriter addInput:assetWriterInput];
else {
NSLog(@"can't add asset writer input... die!");
return;
}
assetWriterInput.expectsMediaDataInRealTime = NO;
[assetWriter startWriting];
[assetReader startReading];
CMTime startTime = CMTimeMake (0, videoAudioTrack.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];
convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);
CMSampleBufferInvalidate(nextBuffer);
CFRelease(nextBuffer);
nextBuffer = NULL;
}
else
{
[assetWriterInput markAsFinished];
// [assetWriter finishWriting];
[assetReader cancelReading];
break;
}
}
}];
这是我在包含 mp3 音轨的视频中遇到的错误:
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '*** -[AVAssetWriterInput
appendSampleBuffer:] Cannot append sample buffer: Input buffer must
be in an uncompressed format when outputSettings is not nil'
任何帮助将不胜感激,谢谢!
您应该可以通过配置 AVAssetReaderOutput
输出设置来实现此目的:
NSDictionary *readerOutputSettings = @{ AVSampleRateKey: @44100, AVFormatIDKey: @(kAudioFormatLinearPCM) };
AVAssetReaderOutput *assetReaderOutput =[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoAudioTrack
outputSettings:readerOutputSettings];
我不是 Obj-C 的本地人,我不得不 google 弄清楚 Swift 中的
这里是 Swift 版本:
let audioSettings: [String : Any] = [
AVFormatIDKey: kAudioFormatLinearPCM,
AVSampleRateKey: 44100
]
let assetReaderAudioOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: audioSettings)