2014-03-12 83 views
5

目标:我想从MP3格式的视频中提取音频。视频可以在任何iOS版支持的格式从MP3格式的视频中提取音频

我曾尝试以下技术来实现上述目标,我用蹩脚的库:

第1步:通过将源文件的URL到它创建一个AVURLAsset对象。

第2步:使用源资源创建AVAssetExportSession对象,将其outputfileType设置为m4a。

第3步:提取其音频,然后我尝试将其转换成MP3格式。

下面是代码,我已经使用:

NSURL *videoFileUrl = [NSURL fileURLWithPath:originalVideoPath]; 
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:videoFileUrl options:nil]; 

exportSession=[AVAssetExportSession exportSessionWithAsset:anAsset presetName:AVAssetExportPresetPassthrough]; 

[exportSession determineCompatibleFileTypesWithCompletionHandler:^(NSArray *compatibleFileTypes) { 
    NSLog(@"compatiblefiletypes: %@",compatibleFileTypes); 
}]; 

NSURL *furl = [NSURL fileURLWithPath:tmpVideoPath]; 
exportSession.outputURL = furl; 
exportSession.outputFileType=AVFileTypeAppleM4A; 

CMTime duration = anAsset.duration; 
CMTimeRange range = CMTimeRangeMake(kCMTimeZero, duration); 
exportSession.timeRange = range; 

[exportSession exportAsynchronouslyWithCompletionHandler:^{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [SVProgressHUD dismiss]; 
    }); 
    switch (exportSession.status) 
    { 
     case AVAssetExportSessionStatusCompleted: 
     { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
        [SVProgressHUD showProgress:0 status:@"Converting..." maskType:SVProgressHUDMaskTypeGradient]; 
        [self performSelector:@selector(convertToMp3) withObject:nil afterDelay:0.3f];  
      }); 
      break; 
     } 
     case AVAssetExportSessionStatusFailed: 
     { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [MyUtility showAlertViewWithTitle:kAlertTitle msg:exportSession.error.localizedDescription]; 
      }); 
      break; 
     } 
     case AVAssetExportSessionStatusCancelled: 
      NSLog(@"Export canceled"); 
      break; 
     default: 

      break; 
    } 
}]; 

__weak AVAssetExportSession *weakSession = exportSession; 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
    while (weakSession.status == AVAssetExportSessionStatusWaiting 
      || weakSession.status == AVAssetExportSessionStatusExporting) { 
     dispatch_sync(dispatch_get_main_queue(), ^{ 
      [SVProgressHUD showProgress:exportSession.progress status:@"Extracting..." maskType:SVProgressHUDMaskTypeGradient]; 
     }); 
    } 
}); 
- (void)convertToMp3 
{ 
NSURL *extractedAudioFileURL = [[NSURL alloc] initWithString:tmpVideoPath]; 
NSError *error; 
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:extractedAudioFileURL error:&error]; 

float noOfChannels = [[audioPlayer.settings objectForKey:AVNumberOfChannelsKey] floatValue]; 
float sampleRate = [[audioPlayer.settings objectForKey:AVSampleRateKey] floatValue]; 
float bitRate = 16;//[[audioPlayer.settings objectForKey:AVLinearPCMBitDepthKey] floatValue]; 

@try { 
    int read, write; 

    FILE *pcm = fopen([tmpVideoPath cStringUsingEncoding:1], "rb"); //source 
    fseek(pcm, 4*1024, SEEK_CUR);         //skip file header 
    FILE *mp3 = fopen([tmpMp3FilePath cStringUsingEncoding:1], "wb"); //output 

    const int PCM_SIZE = 8192; 
    const int MP3_SIZE = 8192; 
    short int pcm_buffer[PCM_SIZE*2]; 
    unsigned char mp3_buffer[MP3_SIZE]; 

    lame_t lame = lame_init(); 
    lame_set_in_samplerate(lame, sampleRate); 
    lame_set_VBR(lame, vbr_default); 
    lame_init_params(lame); 

    long long fileSize = [[[[NSFileManager defaultManager] attributesOfItemAtPath:tmpVideoPath error:nil] objectForKey:NSFileSize] longLongValue]; 
    long duration = (fileSize * 8.0f)/(sampleRate * noOfChannels); 

    lame_set_num_samples(lame, (duration * sampleRate)); 
    lame_get_num_samples(lame); 

    int percent  = 0; 
    int totalframes = lame_get_totalframes(lame); 

    do { 
     read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm); 
     if (read == 0) 
      write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE); 
     else 
      write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE); 

     fwrite(mp3_buffer, write, 1, mp3); 

     int frameNum = lame_get_frameNum(lame); 
     if (frameNum < totalframes) 
      percent = (int) (100. * frameNum/totalframes + 0.5); 
     else 
      percent = 100; 

     [SVProgressHUD showProgress:percent status:@"Converting..." maskType:SVProgressHUDMaskTypeGradient]; 

     NSLog(@"progress: %d",percent); 

    } while (read != 0); 

    lame_close(lame); 
    fclose(mp3); 
    fclose(pcm); 
} 
@catch (NSException *exception) { 
    NSLog(@"%@",[exception description]); 
} 
@finally { 
    [SVProgressHUD dismiss]; 
} 
} 

所产生的音频,我得到了什么,但噪声,其持续时间也是错误的。 我搜索了一下,发现“libmp3lame”只能理解线性PCM音频,因为m4a是压缩音频格式。

现在我怎样才能将音频转换成MP3格式从m4a或任何其他方式直接从视频以MP3格式提取音频。

谢谢。

回答

0

而不是导出到AVFileTypeAppleM4A尝试导出到AVFileTypeAIFF。这将为您提供跛脚编码器所需的线性PCM。临时文件显然会比m4a大,但这可能是您唯一会注意到的差异。

+0

谢谢您的回答,但不幸的是我的应用程序崩溃,如果我的outputfiletype设置为AVFileTypeAIFF和原因是这样的格式与.mov影片兼容 –

+0

嗯...我从来没有过的情况下出口会话couldn”不会导出到它支持的特定格式。如果它可以读取数据,它应该能够导出数据。不知道那里发生了什么,对不起。 – nsdebug

+0

@MuhammadZeeshan我面临着同样的问题。你有没有找到解决办法? –

相关问题