【问题标题】:iOS Audio TrimmingiOS 音频修剪
【发布时间】:2023-03-27 02:16:02
【问题描述】:

我搜索了很多,但找不到任何相关内容...我正在处理 iOS 音频文件,这就是我想要做的...

  1. 录制音频并保存剪辑(已选中,我使用 AVAudioRecorder 完成此操作)
  2. 更改音高(已选中,使用 Dirac 进行此操作)
  3. 修剪:(

我有两个标记,即开始和结束偏移量,使用此信息我想修剪记录的文件并将其保存回来。我不想使用“搜索”,因为稍后我想同步播放所有录制的文件(就像时间轴中的 Flash 电影剪辑一样),最后我想导出为一个音频文件。

【问题讨论】:

  • 感谢 mattjgalloway 的编辑...

标签: ios audio crop seek trim


【解决方案1】:

这是我用来从预先存在的文件中修剪音频的代码。如果您已保存或正在保存为其他格式,则需要更改 M4A 相关常量。

- (BOOL)trimAudio
{
    float vocalStartMarker = <starting time>;
    float vocalEndMarker = <ending time>;

    NSURL *audioFileInput = <your pre-existing file>;
    NSURL *audioFileOutput = <the file you want to create>;

    if (!audioFileInput || !audioFileOutput)
    {
        return NO;
    }

    [[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
    AVAsset *asset = [AVAsset assetWithURL:audioFileInput];

    AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset
                                                                            presetName:AVAssetExportPresetAppleM4A];

    if (exportSession == nil)
    {        
        return NO;
    }

    CMTime startTime = CMTimeMake((int)(floor(vocalStartMarker * 100)), 100);
    CMTime stopTime = CMTimeMake((int)(ceil(vocalEndMarker * 100)), 100);
    CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);

    exportSession.outputURL = audioFileOutput;
    exportSession.outputFileType = AVFileTypeAppleM4A;
    exportSession.timeRange = exportTimeRange;

    [exportSession exportAsynchronouslyWithCompletionHandler:^
     {
         if (AVAssetExportSessionStatusCompleted == exportSession.status)
         {
             // It worked!
         } 
         else if (AVAssetExportSessionStatusFailed == exportSession.status)
         {
             // It failed...
         }
     }];

    return YES;
}

还有Technical Q&A 1730,它给出了一个更详细的方法。

【讨论】:

  • vocalStartMarker 和 vocalEndMarker 在 [0,1] 范围内,对吧?
  • vocalStartMarker 和vocalEndMarker 以秒为单位。例如,修剪 10 秒剪辑的中间秒,您将设置vocalStartMarker = 4.5 和vocalEndMarker = 5.5。
  • 我想我们只是使用:CMTime startTime = CMTimeMake(vocalStartMarker, 1);
  • 导出为m4a格式时如何指定音频比特率?
  • 我使用相同的代码来修剪 15 秒的音频,但我每次都得到不同的秒数。比如 19、16、15 秒。这是代码:float vocalStartMarker = 0.0f;浮动声乐结束标记 = 15.0f; CMTime startTime = CMTimeMake((int)(floor(vocalStartMarker * 100)), 100); CMTime stopTime = CMTimeMake((int)(ceil(vocalEndMarker * 100)), 100); CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);
【解决方案2】:

在 .m 中导入以下两个库

#import "BJRangeSliderWithProgress.h"
#import  < AVFoundation/AVFoundation.h >

粘贴以下代码后,您将能够在两个拇指的帮助下修剪音频文件。

- (void) viewDidLoad
{
      [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

       mySlider = [[BJRangeSliderWithProgress alloc] initWithFrame:CGRectMake(20, 100, 300, 50)];

      [mySlider setDisplayMode:BJRSWPAudioSetTrimMode];

      [mySlider addTarget:self action:@selector(valueChanged) forControlEvents:UIControlEventValueChanged];

      [mySlider setMinValue:0.0];

      NSString *strInputFilePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"saewill.mp3"];

      NSURL *audioFileInput = [NSURL fileURLWithPath:strInputFilePath];

      audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:audioFileInput error:nil];

      [mySlider setMaxValue:audioPlayer.duration];

      [self.view addSubview:mySlider];
}

-(void)valueChanged {
      NSLog(@"%f %f", mySlider.leftValue, mySlider.rightValue);
}


-(IBAction)playTheSong
{
      // Path of your source audio file
      NSString *strInputFilePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"saewill.mp3"];
      NSURL *audioFileInput = [NSURL fileURLWithPath:strInputFilePath];

      // Path of your destination save audio file
      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
      NSString *libraryCachesDirectory = [paths objectAtIndex:0];
      //libraryCachesDirectory = [libraryCachesDirectory stringByAppendingPathComponent:@"Caches"];

      NSString *strOutputFilePath = [libraryCachesDirectory stringByAppendingPathComponent:@"output.mov"];
      NSString *requiredOutputPath = [libraryCachesDirectory stringByAppendingPathComponent:@"output.m4a"];
      NSURL *audioFileOutput = [NSURL fileURLWithPath:requiredOutputPath];

      [[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
      AVAsset *asset = [AVAsset assetWithURL:audioFileInput];

      AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset
                                                                              presetName:AVAssetExportPresetAppleM4A];


      float startTrimTime = mySlider.leftValue;
      float endTrimTime = mySlider.rightValue;

      CMTime startTime = CMTimeMake((int)(floor(startTrimTime * 100)), 100);
      CMTime stopTime = CMTimeMake((int)(ceil(endTrimTime * 100)), 100);
      CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);

      exportSession.outputURL = audioFileOutput;
      exportSession.outputFileType = AVFileTypeAppleM4A;
      exportSession.timeRange = exportTimeRange;

      [exportSession exportAsynchronouslyWithCompletionHandler:^
       {
           if (AVAssetExportSessionStatusCompleted == exportSession.status)
           {
               NSLog(@"Success!");
               NSLog(@" OUtput path is \n %@", requiredOutputPath);
               NSFileManager * fm = [[NSFileManager alloc] init];
               [fm moveItemAtPath:strOutputFilePath toPath:requiredOutputPath error:nil];
               //[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];

               NSURL *url=[NSURL fileURLWithPath:requiredOutputPath];
               NSError *error;
               audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
               audioPlayer.numberOfLoops=0;
               [audioPlayer play];

           }
           else if (AVAssetExportSessionStatusFailed == exportSession.status)
           {
               NSLog(@"failed with error: %@", exportSession.error.localizedDescription);
           }
       }];

}

【讨论】:

  • 你可以通过添加一些关于正在发生的事情的 cmets 来使这个答案更好
  • 屏幕上会有一个滑块,会有两个拇指。在拇指的帮助下,您将能够修剪音频(.m4a)。 @iwantMyAnswerNow
【解决方案3】:

这是一个示例代码,它从开始和结束偏移量修剪音频文件并将其保存回来。 请检查此iOS Audio Trimming

// Path of your source audio file
NSString *strInputFilePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"abc.mp3"];
NSURL *audioFileInput = [NSURL fileURLWithPath:strInputFilePath];

// Path of your destination save audio file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *libraryCachesDirectory = [paths objectAtIndex:0];
    libraryCachesDirectory = [libraryCachesDirectory stringByAppendingPathComponent:@"Caches"];

NSString *strOutputFilePath = [NSString stringWithFormat:@"%@%@",libraryCachesDirectory,@"/abc.mp4"];
NSURL *audioFileOutput = [NSURL fileURLWithPath:strOutputFilePath];

if (!audioFileInput || !audioFileOutput)
{
    return NO;
}

[[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL];
AVAsset *asset = [AVAsset assetWithURL:audioFileInput];

AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:asset presetName:AVAssetExportPresetAppleM4A];

if (exportSession == nil)
{
    return NO;
}
float startTrimTime = 0; 
float endTrimTime = 5;

CMTime startTime = CMTimeMake((int)(floor(startTrimTime * 100)), 100);
CMTime stopTime = CMTimeMake((int)(ceil(endTrimTime * 100)), 100);
CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime);

exportSession.outputURL = audioFileOutput;
exportSession.outputFileType = AVFileTypeAppleM4A;
exportSession.timeRange = exportTimeRange;

[exportSession exportAsynchronouslyWithCompletionHandler:^
{
    if (AVAssetExportSessionStatusCompleted == exportSession.status)
    {
        NSLog(@"Success!");
    }
    else if (AVAssetExportSessionStatusFailed == exportSession.status)
    {
        NSLog(@"failed");
    }
}];

【讨论】:

    【解决方案4】:

    // 斯威夫特 4.2

    如果有人仍然在此处快速寻找答案。

    //音频修剪

    func trimAudio(asset: AVAsset, startTime: Double, stopTime: Double, finished:@escaping (URL) -> ())
    {
    
            let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith:asset)
    
            if compatiblePresets.contains(AVAssetExportPresetMediumQuality) {
    
            guard let exportSession = AVAssetExportSession(asset: asset, 
            presetName: AVAssetExportPresetAppleM4A) else{return}
    
            // Creating new output File url and removing it if already exists.
            let furl = createUrlInAppDD("trimmedAudio.m4a") //Custom Function
            removeFileIfExists(fileURL: furl) //Custom Function
    
            exportSession.outputURL = furl
            exportSession.outputFileType = AVFileType.m4a
    
            let start: CMTime = CMTimeMakeWithSeconds(startTime, preferredTimescale: asset.duration.timescale)
            let stop: CMTime = CMTimeMakeWithSeconds(stopTime, preferredTimescale: asset.duration.timescale)
            let range: CMTimeRange = CMTimeRangeFromTimeToTime(start: start, end: stop)
            exportSession.timeRange = range
    
            exportSession.exportAsynchronously(completionHandler: {
    
                switch exportSession.status {
                case .failed:
                    print("Export failed: \(exportSession.error!.localizedDescription)")
                case .cancelled:
                    print("Export canceled")
                default:
                    print("Successfully trimmed audio")
                    DispatchQueue.main.async(execute: {
                        finished(furl)
                    })
                }
            })
        }
    }
    

    您也可以将其用于视频剪辑。对于视频修剪,将导出会话的值替换为如下:

    guard let exportSession = AVAssetExportSession(asset:asset, presetName: AVAssetExportPresetPassthrough) else{return}

    文件类型为 mp4

    exportSession.outputFileType = AVFileType.mp4

    【讨论】:

    • 嘿,出现此错误操作无法完成。请帮帮我。
    猜你喜欢
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 2013-10-22
    • 2022-07-26
    • 2017-05-05
    • 2012-06-14
    • 1970-01-01
    相关资源
    最近更新 更多