以mp3格式从视频中提取音频

 mobiledu2502874643 发布于 2023-01-18 15:34

目标:我想从mp3格式的视频中提取音频.视频可以采用任何iOS支持的格式

我尝试了以下技术来实现上述目标,我使用的是lame库:

步骤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格式的视频中提取音频.

谢谢.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有