使用淡入淡出保存音频 setVolumeRampFromStartVolume 在 iOS 中不起作用

发布于 2024-12-29 06:28:30 字数 4126 浏览 2 评论 0原文

我正在尝试为 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;
        }       
    }];

I am trying to cut an audio file for an iPhone project. I can cut it and save it, but any fade in / fade out that I try to apply doesn't work, the audio file is just saved cutted but not faded.

I am using the following code:

//
// 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;
        }       
    }];

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

烟花易冷人易散 2025-01-05 06:28:30

您需要选择曲目。除了调用:

AVMutableAudioMixInputParameters *exportAudioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParameters];

Call:

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

AVMutableAudioMixInputParameters *exportAudioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:assetTrack];

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

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

祝您好运!

You need to select the track. Instead of calling:

AVMutableAudioMixInputParameters *exportAudioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParameters];

Call:

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

AVMutableAudioMixInputParameters *exportAudioMixInputParameters = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:assetTrack];

In your existing code you can also specify the track like this:

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

Good luck!

月隐月明月朦胧 2025-01-05 06:28:30

这是解决方案。

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);
    }
}];

Here is the solution.

setVolumeRampFromStartVolume doesn't work.

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

//fade in

[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)];

//fade out

[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);
    }
}];
青萝楚歌 2025-01-05 06:28:30

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

CMTimeRange fadeInTimeRange = CMTimeRangeFromTimeToTime(startFadeInTime, endFadeInTime);

CMTimeRange fadeOutTimeRange = CMTimeRangeFromTimeToTime(startFadeOutTime, endFadeOutTime);

应该是:

CMTimeRangeFromTimeToTime(startFadeInTime, fadeInDURATION);

CMTimeRangeFromTimeToTime(startFadeOutTime, fadeOutDURATION);

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

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

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

I've made the same mistake as you dozens of times !
Apple's API is really weird on this :

CMTimeRange fadeInTimeRange = CMTimeRangeFromTimeToTime(startFadeInTime, endFadeInTime);

CMTimeRange fadeOutTimeRange = CMTimeRangeFromTimeToTime(startFadeOutTime, endFadeOutTime);

Should be :

CMTimeRangeFromTimeToTime(startFadeInTime, fadeInDURATION);

CMTimeRangeFromTimeToTime(startFadeOutTime, fadeOutDURATION);

CMTimeRange is created from start and duration, not from start and end !

But most of the time, the end time is also the duration (if the start time is 0) that's why so many people (including me) make the mistake.

And no Apple, that's not intuitive at all !

眼睛会笑 2025-01-05 06:28:30

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

+(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);
    }];
}

This is my working code, just take it and have a nice day!

+(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);
    }];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文