mobile-ffmpeg
项目适配需12.1以上
pod 'mobile-ffmpeg-full', '~> 4.4'
#import <mobileffmpeg/MobileFFmpegConfig.h>
#import <mobileffmpeg/MobileFFprobe.h>
需求功能:视频提取音频,转换格式等
视频指定时间添加音频
-y -i /storage/emulated/0/DCIM/Camera/1632297306905.mp4 -i /storage/emulated/0/szshht/TempFile/16323885018260.mp3 -i /storage/emulated/0/szshht/TempFile/16323885018261.mp3 -filter_complex [1]adelay=728|728[del1],[2]adelay=7015|7015[del2],[0][del1][del2]amix=3 /storage/emulated/0/szshht/TempFile/Dubbing_20210923_171503.mp4
Swift
// 视频提取音频
if let avAssets = assets as? AVURLAsset {
let outputURL = self.exporterPath(filename: "mp3")
let rc = MobileFFmpeg.execute("-i \(avAssets.url.path) -ar 16000 -ac 1 \(outputURL.path)")
if (rc == RETURN_CODE_SUCCESS) {
tsPrint("Command execution completed successfully.\n")
HUD.hideLoadingView()
self.videoUrl = outputURL
} else if (rc == RETURN_CODE_CANCEL) {
tsPrint("Command execution cancelled by user.\n")
HUD.showInfo(info: "Command execution cancelled by user.")
} else {
tsPrint("Command execution failed with output=\(String(describing: MobileFFmpegConfig.getLastCommandOutput())).\n")
HUD.showInfo(info: "Command execution failed")
}
}
func exporterPath(filename: String) -> URL {
let formatter = DateFormatter.init()
formatter.dateFormat = "yyyyMMddHHmmss"
let str = formatter.string(from: Date.init())
let fileName = "selfMusic\(str).\(filename)"
let path = kVideoCachePath
//判断文件夹是否存在,不存在就创建
//创建附件存储目录
if FileManager.default.fileExists(atPath: path) == false {
try? FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
}
let outputFilePath = "\(path)\(fileName)"
return URL.init(fileURLWithPath: outputFilePath)
}
OC
// 视频提取音频
NSURL *toUrl = [NSURL exporterPath:@"mp3"];
NSString *ffmpegString = [NSString stringWithFormat:@"-i %@ -ar 16000 -ac 1 %@", urlAsset.URL.path, toUrl.path];
DEBUGLOG(@"ffmpegString --- %@", ffmpegString);
int rc = [MobileFFmpeg execute:ffmpegString];
if (rc == RETURN_CODE_SUCCESS) {
DEBUGLOG(@"合成成功");
WEAKSELF
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf recognizeWithAudioDataWith:toUrl];
});
} else if (rc == RETURN_CODE_CANCEL) {
DEBUGLOG(@"Command execution cancelled by user.\n");
} else {
[TSWindowHudService showViewWithFailed:@"Command execution failed with rc"];
DEBUGLOG(@"Command execution failed with rc=%d and output=%@.\n", rc, [MobileFFmpegConfig getLastCommandOutput]);
}
多音频合成
- (void)hechengMethods {
[TSWindowHudService showLoadingViewWithInfo:@"正在合成配音..."];
NSString *inputString = @"";
NSString *contentString = @"";
for (VDSynthesisModel *model in self.tableData) {
inputString = [inputString stringByAppendingString:[NSString stringWithFormat:@"%@|", model.pathString]];
contentString = [contentString stringByAppendingString:model.contentString];
contentString = [contentString stringByAppendingString:@"\n\n"];
}
inputString = [inputString substringToIndex:inputString.length - 1];
NSURL *url = [NSURL exporterPathString:kHuanCunPathString filename:@"mp3"];
NSString *ffmpegString = [NSString stringWithFormat:@"-y -i concat:%@ -acodec copy %@", inputString, url.path];
DEBUGLOG(@"ffmpegString --- %@", ffmpegString);
int rc = [MobileFFmpeg execute:ffmpegString];
if (rc == RETURN_CODE_SUCCESS) {
DEBUGLOG(@"合成成功");
[TSWindowHudService hideLoadingView];
VDStaffDoneViewController *vc = [[VDStaffDoneViewController alloc] init];
vc.voiceUrlString = url.path;
vc.staffPathUrl = url;
vc.downPathUrl = url;
vc.contentString = contentString;
[self.navigationController pushViewController:vc animated:YES];
} else if (rc == RETURN_CODE_CANCEL) {
DEBUGLOG(@"Command execution cancelled by user.\n");
} else {
DEBUGLOG(@"Command execution failed with rc=%d and output=%@.\n", rc, [MobileFFmpegConfig getLastCommandOutput]);
}
}
/// 输出路径
+ (NSURL *)exporterPathString:(NSString *)pathString filename:(NSString *)filename {
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
formatter.dateFormat = @"yyyyMMdd_HHmmssSSS";
NSString *str = [formatter stringFromDate:[NSDate date]];
NSString *fileName = [NSString stringWithFormat:@"PYB_%@.%@", str, filename];
//这个是录制视频时存储到本地的video
NSString *path = pathString;
//判断文件夹是否存在,不存在就创建
//创建附件存储目录
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *outputFilePath = [path stringByAppendingPathComponent:fileName];
return [NSURL fileURLWithPath:outputFilePath];
}
#define kHuanCunPathString [kLOCALDIR stringByAppendingPathComponent:kHuanCun_String] // 下载缓存路径
#define kLOCALDIR [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]
打印命令:-y -i concat:/var/mobile/Containers/Data/Application/7FFCB997-F3F6-4274-A87B-214D763018F4/Documents/HuanCun/PYB_20220112_145907336.mp3|/var/mobile/Containers/Data/Application/7FFCB997-F3F6-4274-A87B-214D763018F4/Documents/HuanCun/PYB_20220112_145907340.mp3 -acodec copy /var/mobile/Containers/Data/Application/7FFCB997-F3F6-4274-A87B-214D763018F4/Documents/HuanCun/PYB_20220112_145907659.mp3
背景音乐合成
- (void)backgroundMusicCompositionMethod {
NSURL *url = [NSURL exporterPathString:kHuanCunPathString filename:@"mp3"];
int rc = [MobileFFmpeg execute:[NSString stringWithFormat:@"-i %@ -i %@ -filter_complex amix=inputs=2:duration=first:dropout_transition=2 -f mp3 %@", self.staffPathUrl.path, self.backMusicPathString, url.path]];
if (rc == RETURN_CODE_SUCCESS) {
DEBUGLOG(@"合成成功");
WEAKSELF
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
weakSelf.downPathUrl = url;
kPlayer.playUrlStr = weakSelf.downPathUrl.path;
[kPlayer play];
});
} else if (rc == RETURN_CODE_CANCEL) {
DEBUGLOG(@"Command execution cancelled by user.\n");
} else {
DEBUGLOG(@"Command execution failed with rc=%d and output=%@.\n", rc, [MobileFFmpegConfig getLastCommandOutput]);
}
}
网友评论