【问题标题】:What iOS framework is needed for this particular audio manipulation这种特定的音频操作需要什么 iOS 框架
【发布时间】:2012-08-23 14:53:38
【问题描述】:

在我坐下来阅读有关 CoreAudio 的整本书之前,我想知道它是否是我学习的最佳框架,或者 AVFoundation 是否可以满足我的需求。我希望能够下载位于远程服务器上的 MP3 的一小部分,比如说 20 秒的文件,最好不要先下载整个文件然后修剪它。

然后我想将 2 个音频轨道分层,然后将它们合并为一个文件。

我是否需要深入研究 CoreAudio 或者 AVFoundation 可以这样吗?非常感谢您的建议。

【问题讨论】:

    标签: objective-c ios xcode avfoundation core-audio


    【解决方案1】:

    文件的下载部分由你决定,但如果你想将 2 个或多个音频文件混合为一个,AVFoundation 可能是最简单的方法,使用AVAssetExportSession 进行导出和AVMutableAudioMix 到做混合..在苹果文档中有一些简单编辑器的示例代码,但似乎找不到它,如果我找到它,我会发布链接..

    这是一种实际进行混合的方法,请记住,我也在此处添加视频,_audioTracks 和 _videoTracks 是其中包含 AVAssets 的可变数组

    -(void)createMix
    {
    
        CGSize videoSize = [[_videoTracks objectAtIndex:0] naturalSize];
        AVMutableComposition *composition = [AVMutableComposition composition];
        AVMutableVideoComposition *videoComposition = nil;
        AVMutableAudioMix *audioMix = nil;
    
        composition.naturalSize = videoSize;
    
    
        AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
        AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    
    
    
        AVAsset *videoAsset=[_videoTracks objectAtIndex:0];
       CMTimeRange  timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [videoAsset duration]);
            AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
            [compositionVideoTrack insertTimeRange:timeRangeInAsset ofTrack:clipVideoTrack atTime:kCMTimeZero error:nil];
    
            AVAssetTrack *clipAudioTrack = [[videoAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
            [compositionAudioTrack insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
    
    
        NSMutableArray *trackMixArray = [NSMutableArray array];
    
        if(_audioTracks && _audioTracks.count>0)
        {
            for(AVAsset *audio in _audioTracks)
            {
              //     CMTimeRange  timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [audio duration]);
               // AVAssetTrack *clipAudioTrack = [[audio tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
                //[compositionAudioTrack insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil];
    
    
                NSInteger i;
                NSArray *tracksToDuck = [audio tracksWithMediaType:AVMediaTypeAudio]; // before we add the commentary
    
                // Clip commentary duration to composition duration.
                CMTimeRange commentaryTimeRange = CMTimeRangeMake(kCMTimeZero, audio.duration);
                if (CMTIME_COMPARE_INLINE(CMTimeRangeGetEnd(commentaryTimeRange), >, [composition duration]))
                    commentaryTimeRange.duration = CMTimeSubtract([composition duration], commentaryTimeRange.start);
    
                // Add the commentary track.
                AVMutableCompositionTrack *compositionCommentaryTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
                [compositionCommentaryTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, commentaryTimeRange.duration) ofTrack:[[audio tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:commentaryTimeRange.start error:nil];
    
    
    
                CMTime rampDuration = CMTimeMake(1, 2); // half-second ramps
                for (i = 0; i < [tracksToDuck count]; i++) {
                    AVMutableAudioMixInputParameters *trackMix = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:[tracksToDuck objectAtIndex:i]];
                    [trackMix setVolumeRampFromStartVolume:1.0 toEndVolume:0.2 timeRange:CMTimeRangeMake(CMTimeSubtract(commentaryTimeRange.start, rampDuration), rampDuration)];
                    [trackMix setVolumeRampFromStartVolume:0.2 toEndVolume:1.0 timeRange:CMTimeRangeMake(CMTimeRangeGetEnd(commentaryTimeRange), rampDuration)];
                    [trackMixArray addObject:trackMix];
    
                }
    
    
            }
        }
    
         // audioMix.inputParameters = trackMixArray;
    
        if (videoComposition) {
            // Every videoComposition needs these properties to be set:
            videoComposition.frameDuration = CMTimeMake(1, 30); // 30 fps
            videoComposition.renderSize = videoSize;
        }
    
    
        AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPreset1280x720];
        session.videoComposition = videoComposition;
        session.audioMix = audioMix;
    
        NSUInteger count = 0;
        NSString *filePath;
        do {
            filePath = NSTemporaryDirectory();
    
            NSString *numberString = count > 0 ? [NSString stringWithFormat:@"-%i", count] : @"";
            filePath = [filePath stringByAppendingPathComponent:[NSString stringWithFormat:@"Output-%@.mp4", numberString]];
            count++;
        } while([[NSFileManager defaultManager] fileExistsAtPath:filePath]);      
    
        session.outputURL = [NSURL fileURLWithPath:filePath];
        session.outputFileType = AVFileTypeQuickTimeMovie;
    
         [session exportAsynchronouslyWithCompletionHandler:^
         {
             dispatch_async(dispatch_get_main_queue(), ^{
                 NSLog(@"Exported");
                 if(session.error)
                 {
                     NSLog(@"had an error %@", session.error);
                 }
                 if(delegate && [delegate respondsToSelector:@selector(didFinishExportingMovie:)])
                 {
                     [delegate didFinishExportingMovie:filePath];
                 }
    
    
         });
         }];
    
    
    
    }
    

    希望对你有帮助..

    丹尼尔

    【讨论】:

    • 感谢丹尼尔的帮助。你说的由我决定,你的意思是必须先下载整个文件,然后我才能修剪它?
    • @Wasim 可以下载其中的一部分,但我的意思是你必须弄清楚你需要多少字节,标题在哪里(如果有的话)等等。那里是在 iOS 中执行此操作的方法,但我很确定您需要为此拥有整个文件..
    • 非常感谢您提供的代码,这将是一个真正的帮助。因此,如果 URL 是 MP3 的直接链接,那么标头是否会包含有关字节等的所有信息?难道我不能根据它计算所需的字节数吗?另外,我需要开始学习哪些课程才能完成这项工作?再次感谢您的帮助。
    • @Wasim 那么让你开始看看这个问题并回答stackoverflow.com/questions/7375309/…我不确定你是否可以让它处理部分文件..假设你有答案中使用的数据,那么你应该可以使用代码来计算你需要多少字节
    • 谢谢丹尼尔,帮了大忙!我来看看答案。
    猜你喜欢
    • 2012-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多