2014-03-12 114 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我面臨着同樣的問題。你有沒有找到解決辦法? –

相關問題