【问题标题】:Save audio with fade in fade out with setVolumeRampFromStartVolume not working in iOS使用 setVolumeRampFromStartVolume 淡入淡出保存音频在 iOS 中不起作用
【发布时间】:2012-01-28 14:02:15
【问题描述】:

我正在尝试为 iPhone 项目剪切音频文件。我可以剪切并保存它,但是我尝试应用的任何淡入/淡出都不起作用,音频文件只是保存剪切而不是淡出。

我正在使用以下代码:

//
// NO PROBLEMS TO SEE HERE, MOVE ON
//
    NSArray *documentsFolders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    int currentFileNum = 10;
    NSURL *url = [NSURL fileURLWithPath: [[documentsFolders objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%d.%@", AUDIO_SOURCE_FILE_NAME ,currentFileNum, AUDIO_SOURCE_FILE_EXTENSION ]]];
    NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                        forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:options];
    AVAssetExportSession* exporter = [AVAssetExportSession exportSessionWithAsset:asset presetName:AVAssetExportPresetAppleM4A];

    for (NSString* filetype in exporter.supportedFileTypes) {
        if ([filetype isEqualToString:AVFileTypeAppleM4A]) {
            exporter.outputFileType = AVFileTypeAppleM4A;
            break;
        }
    }
    if (exporter.outputFileType == nil) {
        NSLog(@"Needed output file type not found? (%@)", AVFileTypeAppleM4A);
        //return;
    }

    NSString* outPath = [[documentsFolders objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%d.%@", AUDIO_CUTTED_FILE_NAME ,currentFileNum, AUDIO_SOURCE_FILE_EXTENSION ]];

    NSURL* const outUrl = [NSURL fileURLWithPath:outPath];
    exporter.outputURL = outUrl;

    float endTrimTime = CMTimeGetSeconds(asset.duration);
    float startTrimTime = fminf(AUDIO_DURATION, endTrimTime);
    CMTime startTrimCMTime=CMTimeSubtract(asset.duration, CMTimeMake(startTrimTime, 1));
    exporter.timeRange = CMTimeRangeMake(startTrimCMTime, asset.duration);

//
// TRYING TO APPLY FADEIN FADEOUT, NOT WORKING, NO RESULTS, "CODE IGNORED"
//
    AVMutableAudioMix *exportAudioMix = [AVMutableAudioMix audioMix];

    NSMutableArray* inputParameters = [NSMutableArray arrayWithCapacity:1];

    CMTime startFadeInTime = startTrimCMTime;
    CMTime endFadeInTime = CMTimeMake(startTrimTime+1, 1);
    CMTime startFadeOutTime = CMTimeMake(endTrimTime-1, 1);
    CMTime endFadeOutTime = CMTimeMake(endTrimTime, 1);

    CMTimeRange fadeInTimeRange = CMTimeRangeFromTimeToTime(startFadeInTime, endFadeInTime);

    CMTimeRange fadeOutTimeRange = CMTimeRangeFromTimeToTime(startFadeOutTime, endFadeOutTime);

    AVMutableAudioMixInputParameters *exportAudioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParameters];
    [exportAudioMixInputParameters setVolume:0.0 atTime:CMTimeMakeWithSeconds(startTrimTime-0.01, 1)];
    [exportAudioMixInputParameters setVolumeRampFromStartVolume:0.0 toEndVolume:1.0 timeRange:fadeInTimeRange];
    [exportAudioMixInputParameters setVolumeRampFromStartVolume:1.0 toEndVolume:0.0 timeRange:fadeOutTimeRange];

    [inputParameters insertObject:exportAudioMixInputParameters atIndex:0];

    exportAudioMix.inputParameters = inputParameters;
    exporter.audioMix = exportAudioMix;

    [exporter exportAsynchronouslyWithCompletionHandler:^(void) {
        NSString* message;
        switch (exporter.status) {
            case AVAssetExportSessionStatusFailed:
                message = [NSString stringWithFormat:@"Export failed. Error: %@", exporter.error.description];
                [asset release];
                break;
            case AVAssetExportSessionStatusCompleted: {
                [asset release];
                [self reallyConvert:currentFileNum];
                message = [NSString stringWithFormat:@"Export completed: %@", outPath];
                break;
            }
            case AVAssetExportSessionStatusCancelled:
                message = [NSString stringWithFormat:@"Export cancelled!"];
                [asset release];
                break;
            default:
                NSLog(@"Export 4 unhandled status: %d", exporter.status);
                [asset release];
                break;
        }       
    }];

【问题讨论】:

  • 你找到解决办法了吗?请帮忙。

标签: iphone objective-c ios avassetexportsession cmtime


【解决方案1】:

您需要选择曲目。而不是调用:

AVMutableAudioMixInputParameters *exportAudioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParameters];

呼叫:

AVAssetTrack *assetTrack = [[asset tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0];

AVMutableAudioMixInputParameters *exportAudioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:assetTrack];

在您现有的代码中,您还可以像这样指定轨道:

exportAudioMixInputParameters.trackID = [[[asset tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0] trackID];

祝你好运!

【讨论】:

    【解决方案2】:

    这是解决方案。

    setVolumeRampFromStartVolume 不起作用。

    AVMutableAudioMix *exportAudioMix = [AVMutableAudioMix audioMix];
    AVMutableAudioMixInputParameters *exportAudioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track];
    

    //淡入

    [exportAudioMixInputParameters setVolume:0.0 atTime:CMTimeMakeWithSeconds(start-1, 1)];
    [exportAudioMixInputParameters setVolume:0.1 atTime:CMTimeMakeWithSeconds(start, 1)];
    [exportAudioMixInputParameters setVolume:0.5 atTime:CMTimeMakeWithSeconds(start+1, 1)];
    [exportAudioMixInputParameters setVolume:1.0 atTime:CMTimeMakeWithSeconds(start+2, 1)];
    

    //淡出

    [exportAudioMixInputParameters setVolume:1.0 atTime:CMTimeMakeWithSeconds((start+length-2), 1)];
    [exportAudioMixInputParameters setVolume:0.5 atTime:CMTimeMakeWithSeconds((start+length-1), 1)];
    [exportAudioMixInputParameters setVolume:0.1 atTime:CMTimeMakeWithSeconds((start+length), 1)];
    
    exportAudioMix.inputParameters = [NSArray arrayWithObject:exportAudioMixInputParameters];
    
    
    // configure export session  output with all our parameters
    exportSession.outputURL = [NSURL fileURLWithPath:filePath]; // output path
    exportSession.outputFileType = AVFileTypeAppleM4A; // output file type
    exportSession.timeRange = exportTimeRange; // trim time ranges
    exportSession.audioMix = exportAudioMix; // fade in audio mix
    // perform the export
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
    
        if (AVAssetExportSessionStatusCompleted == exportSession.status) {
            NSLog(@"AVAssetExportSessionStatusCompleted");
    
        } else if (AVAssetExportSessionStatusFailed == exportSession.status) {
            NSLog(@"AVAssetExportSessionStatusFailed");
    
        } else {
            NSLog(@"Export Session Status: %d", exportSession.status);
        }
    }];
    

    【讨论】:

    • 这是大多数人犯的错误,因此看不到 setVolumeRampFromStartVolume 工作。 (这是我到目前为止所经历的)。不要做:CMTimeRangeMake(start time, end time) 但是做:CMTimeRangeMake(start time, range duration) 我犯了几十次这个错误,因为如果你的持续时间从0开始,范围持续时间=结束时间但是在这种情况下淡出,它不是!
    【解决方案3】:

    我和你一样的错误已经犯了几十次了! Apple 的 API 在这方面真的很奇怪:

    CMTimeRange fadeInTimeRange = CMTimeRangeFromTimeToTime(startFadeInTime, endFadeInTime);
    
    CMTimeRange fadeOutTimeRange = CMTimeRangeFromTimeToTime(startFadeOutTime, endFadeOutTime);
    

    应该是:

    CMTimeRangeFromTimeToTime(startFadeInTime, fadeInDURATION);
    
    CMTimeRangeFromTimeToTime(startFadeOutTime, fadeOutDURATION);
    

    CMTimeRange 是从开始和持续时间创建的,而不是从开始和结束创建的!

    但大多数时候,结束时间也是持续时间(如果开始时间为 0),这就是为什么这么多人(包括我)会犯错误的原因。

    没有苹果,这根本不直观!

    【讨论】:

      【解决方案4】:

      这是我的工作代码,拿着它,祝你有美好的一天!

      +(void)makeAudioFadeOutWithSourceURL:(NSURL*)sourceURL destinationURL:(NSURL*)destinationURL fadeOutBeginSecond:(NSInteger)beginTime fadeOutEndSecond:(NSInteger)endTime fadeOutBeginVolume:(CGFloat)beginVolume fadeOutEndVolume:(CGFloat)endVolume callback:(void(^)(BOOL))callback
      {
          NSAssert(callback, @"need callback");
          NSParameterAssert(beginVolume >= 0 && beginVolume <=1);
          NSParameterAssert(endVolume >= 0 && endVolume <= 1);
      
          BOOL sourceExist = [[NSFileManager defaultManager] fileExistsAtPath:sourceURL.path];
          NSAssert(sourceExist, @"source not exist");
      
          AVURLAsset *asset = [AVAsset assetWithURL:sourceURL];;
      
          AVAssetExportSession* exporter = [AVAssetExportSession exportSessionWithAsset:asset presetName:AVAssetExportPresetAppleM4A];
      
          exporter.outputURL = destinationURL;
          exporter.outputFileType = AVFileTypeAppleM4A;
      
          AVMutableAudioMix *exportAudioMix = [AVMutableAudioMix audioMix];
      
          AVMutableAudioMixInputParameters *exportAudioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:asset.tracks.lastObject];
          [exportAudioMixInputParameters setVolumeRampFromStartVolume:beginVolume toEndVolume:endVolume timeRange:CMTimeRangeMake(CMTimeMakeWithSeconds(beginTime, 1), CMTimeSubtract(CMTimeMakeWithSeconds(endTime, 1), CMTimeMakeWithSeconds(beginTime, 1)))];
          NSArray *audioMixParameters = @[exportAudioMixInputParameters];
          exportAudioMix.inputParameters = audioMixParameters;
      
          exporter.audioMix = exportAudioMix;
      
          [exporter exportAsynchronouslyWithCompletionHandler:^(void){
              AVAssetExportSessionStatus status = exporter.status;
              if (status != AVAssetExportSessionStatusCompleted) {
                  if (callback) {
                      callback(NO);
                  }
              }
              else {
                  if (callback) {
                      callback(YES);
                  }
              }
              NSError *error = exporter.error;
              NSLog(@"export done,error %@,status %d",error,status);
          }];
      }
      

      【讨论】:

        猜你喜欢
        • 2015-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多