簡體   English   中英

AVAssetWriter如何編寫向下采樣/壓縮的m4a / mp3文件

[英]AVAssetWriter How to write down-sampled/compressed m4a/mp3 files

我正在嘗試獲取本地m4a或mp3文件並對該文件進行壓縮/降采樣(以制作更小的文件)。

最初,我使用AVAssetExportSession將AVAsset導出到臨時目錄,但是我對壓縮/下采樣沒有任何控制權(只能使用預設,其中只有.wav文件格式支持質量降級) 。

然后,按照SO上的幾個示例,我嘗試使用AVAssetReader / AVAssetWriter進行此“導出”。

我這樣創建我的讀者/作家:

NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"];

NSURL *exportURL = [NSURL fileURLWithPath:outPath];

// reader
NSError *readerError = nil;
AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:asset
                                                       error:&readerError];

AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];    
AVAssetReaderTrackOutput *readerOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track
                                                                          outputSettings:nil];
[reader addOutput:readerOutput];

// writer
NSError *writerError = nil;
AVAssetWriter *writer = [[AVAssetWriter alloc] initWithURL:exportURL
                                                  fileType:AVFileTypeAppleM4A
                                                     error:&writerError];

AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;

// use different values to affect the downsampling/compression
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
                                [NSNumber numberWithFloat:44100.0], AVSampleRateKey,
                                [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
                                [NSNumber numberWithInt:128000], AVEncoderBitRateKey,
                                [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
                                nil];

AVAssetWriterInput *writerInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio
                                                                 outputSettings:outputSettings];
[writerInput setExpectsMediaDataInRealTime:NO];
[writer addInput:writerInput];

然后我開始寫...

[writer startWriting];
[writer startSessionAtSourceTime:kCMTimeZero];

[reader startReading];
dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
[writerInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^{

    NSLog(@"Asset Writer ready : %d", writerInput.readyForMoreMediaData);
    while (writerInput.readyForMoreMediaData) {
        CMSampleBufferRef nextBuffer;
        if ([reader status] == AVAssetReaderStatusReading && (nextBuffer = [readerOutput copyNextSampleBuffer])) {
            if (nextBuffer) {
                NSLog(@"Adding buffer");
                [writerInput appendSampleBuffer:nextBuffer];
            }
        } else {
            [writerInput markAsFinished];

            switch ([reader status]) {
                case AVAssetReaderStatusReading:
                    break;
                case AVAssetReaderStatusFailed:
                    [writer cancelWriting];
                    break;
                case AVAssetReaderStatusCompleted:
                    NSLog(@"Writer completed");
                    [writer endSessionAtSourceTime:asset.duration];
                    [writer finishWriting];

                    NSData *data = [NSData dataWithContentsOfFile:exportPath];
                    NSLog(@"Data: %@", data);
                    break;
            }
            break;
        }
    }
}];

當我寫完后,我應該寫到exportURL的數據為空,並且編寫器報告成功完成。 任何想法可能出什么問題嗎?

更新調用appendSampleBuffer:之后的appendSampleBuffer:器狀態為AVAssetWriterStatusFailed,盡管讀取器狀態為成功,並且似乎可以讀取整個文件。

我遇到了解決方案:

NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"]使用NSHomeDirectory() NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"]導致NSString *exportPath = [NSHomeDirectory() stringByAppendingPathComponent:@"out.m4a"]無法創建文件。 不完全確定為什么,或者我需要做些什么才能NSTemporaryDirectory()正常工作,但是將NSHomeDirectiory()更改為NSTemporaryDirectory()已經解決了我的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM