【问题标题】:iOS Remove Particular Sound from a videoiOS 从视频中删除特定声音
【发布时间】:2023-08-02 13:21:01
【问题描述】:

我有一个应用程序可以播放一些音频并在播放声音时录制视频+音频。我想找出一种处理视频的方法,以便从生成的视频中删除麦克风拾取的音频。

例如,如果我正在播放音频 A,然后使用音频 B(来自麦克风)录制视频 B,我想以某种方式从生成的音频 B 中消除音频 A,以便音频 B 只是环境噪声而不是来自设备扬声器。

知道有没有办法做到这一点?

如果可以在没有任何离线处理的情况下完成,则可以加分。

【问题讨论】:

    标签: ios audio avfoundation noise-reduction echo-cancellation


    【解决方案1】:

    您必须处理播放部分。但这里有一个将所选音频混合到录制视频的代码。

    - (void)mixAudio:(AVAsset*)audioAsset startTime:(CMTime)startTime withVideo:(NSURL*)inputUrl affineTransform:(CGAffineTransform)affineTransform  toUrl:(NSURL*)outputUrl outputFileType:(NSString*)outputFileType withMaxDuration:(CMTime)maxDuration withCompletionBlock:(void(^)(NSError *))completionBlock {
        NSError * error = nil;
        AVMutableComposition * composition = [[AVMutableComposition alloc] init];
    
        AVMutableCompositionTrack * videoTrackComposition = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
    
        AVMutableCompositionTrack * audioTrackComposition = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
    
        AVURLAsset * fileAsset = [AVURLAsset URLAssetWithURL:inputUrl options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]];
    
        NSArray * videoTracks = [fileAsset tracksWithMediaType:AVMediaTypeVideo];
    
        CMTime duration = ((AVAssetTrack*)[videoTracks objectAtIndex:0]).timeRange.duration;
    
        if (CMTIME_COMPARE_INLINE(duration, >, maxDuration)) {
            duration = maxDuration;
        }
    
        for (AVAssetTrack * track in [audioAsset tracksWithMediaType:AVMediaTypeAudio]) {
            [audioTrackComposition insertTimeRange:CMTimeRangeMake(startTime, duration) ofTrack:track atTime:kCMTimeZero error:&error];
    
            if (error != nil) {
                completionBlock(error);
                return;
            }
        }
    
        for (AVAssetTrack * track in videoTracks) {
            [videoTrackComposition insertTimeRange:CMTimeRangeMake(kCMTimeZero, duration) ofTrack:track atTime:kCMTimeZero error:&error];
    
            if (error != nil) {
                completionBlock(error);
                return;
            }
        }
    
        videoTrackComposition.preferredTransform = affineTransform;
    
        AVAssetExportSession * exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetPassthrough];
        exportSession.outputFileType = outputFileType;
        exportSession.shouldOptimizeForNetworkUse = YES;
        exportSession.outputURL = outputUrl;
    
        [exportSession exportAsynchronouslyWithCompletionHandler:^ {
            NSError * error = nil;
            if (exportSession.error != nil) {
                NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithDictionary:exportSession.error.userInfo];
                NSString * subLocalizedDescription = [userInfo objectForKey:NSLocalizedDescriptionKey];
                [userInfo removeObjectForKey:NSLocalizedDescriptionKey];
                [userInfo setObject:@"Failed to mix audio and video" forKey:NSLocalizedDescriptionKey];
                [userInfo setObject:exportSession.outputFileType forKey:@"OutputFileType"];
                [userInfo setObject:exportSession.outputURL forKey:@"OutputUrl"];
                [userInfo setObject:subLocalizedDescription forKey:@"CauseLocalizedDescription"];
    
                [userInfo setObject:[AVAssetExportSession allExportPresets] forKey:@"AllExportSessions"];
    
                error = [NSError errorWithDomain:@"Error" code:500 userInfo:userInfo];
            }
    
            completionBlock(error);
        }];
    }
    

    【讨论】:

    • 看起来很酷的项目,但乍一看我并没有看到如何按照我的建议去做。
    • 我认为你不明白我的问题。我的视频和音频很好地结合在一起。问题是,录音还包括从扬声器发出的环境噪音(这是我在应用程序中播放的音频。)我想要某种方法来消除最终录音中的噪音。
    • 换句话说。想象一下,我的应用程序正在通过扬声器播放莫扎特,同时记录用户所说的话。我希望录音不包括莫扎特,即使麦克风正在拾取它。
    • 这可能需要某种信号处理才能弄清楚或类似的东西。
    • 好的。它的参与比我想象的要多。在此处查看此链接*.com/questions/10903542/… 您可以尝试将音频会话类别设置为不同的值,然后在进行音频取消路由之前尝试一下(例如 [AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback])。