当前位置: 首页 > article >正文

iOS 集成ffmpeg

前言

本来打算用flutter去实现一个ffmpeg的项目的,不过仔细分析了一下,我后期需要集成OpenGL ES做视频渲染处理,OpenGL ES的使用目前在flutter上面还不是很成熟,所以最后还是选择用原生来开发

ffmpeg集成到iOS工程

iOS对于ffmpeg的使用,看了网上,很多人说自己去编译ffmpeg源码,弄了半天,没弄好,放弃了,直接使用现成的第三方库 ffmpeg-kit-ios-full-gpl

这是我工程的Podfile文件

platform:ios,'13.0'

target 'ffmpeg03' do
pod 'ffmpeg-kit-ios-full-gpl', '6.0'

end

遇到的问题

集成上面的裤,pod install之后,工程是运行不起来的,会报下面的错误:

Sandbox: rsync(31518) deny(1) file-write-create

解决方法 

方法一:修改Targets -> Build Settings 中 ENABLE_USER_SCRIPT_SANDBOXING 设置 NO

image.png

方法二:项目使用cocoaPods进行三方管理 且 使用了 use_frameworks,把 use_frameworks 注释掉,重新pod install 然后运行

platform:ios,'13.0'

target 'ffmpeg03' do
pod 'ffmpeg-kit-ios-full-gpl', '6.0'

end

编译通过

测试

工程目录:

 项目代码

实现一个视频从mp4转avi

import ffmpegkit
import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        convertVideoFormat()
    }
    
    func convertVideoFormat() {
        // 获取输入文件路径
        guard let inputFile = Bundle.main.path(forResource: "12345", ofType: "mp4") else {
            print("未找到输入文件")
            return
        }
        
        // 设置输出文件路径
        let documentsDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        let outputFile = "\(documentsDir)/output.avi"
        
        // 构建 FFmpeg 命令
        let ffmpegCommand = "-i \"\(inputFile)\" -c:v libx264 -c:a aac \"\(outputFile)\""
        print("执行的命令:ffmpeg \(ffmpegCommand)")
        
        // 执行转换
        FFmpegKit.executeAsync(ffmpegCommand) { session in
            let state = session?.getState()
            let returnCode = session?.getReturnCode()
            
            print("Return Code:\(String(describing: returnCode))")
            
            if ReturnCode.isSuccess(returnCode) {
                // 转换成功
                print("视频转换成功!输出文件位于:\(outputFile)")
                DispatchQueue.main.async {
                    // 在主线程中更新 UI 或进行下一步操作
                }
            } else {
                // 转换失败
                if let output = session?.getAllLogsAsString() {
                    print("转换失败,输出日志:\n\(output)")
                }
                if let failStackTrace = session?.getFailStackTrace() {
                    print("失败堆栈跟踪:\n\(failStackTrace)")
                }
            }
        }
    }
}

最终输出


http://www.kler.cn/a/516702.html

相关文章:

  • C语言文件操作
  • Android SystemUI——系统快捷设置面板(十三)
  • No.36 学习 | Python 函数:从基础到实战
  • 【IEEE Fellow 主讲报告| EI检索稳定】第五届机器学习与智能系统工程国际学术会议(MLISE 2025)
  • 基于 WEB 开发的手机销售管理系统设计与实现内容
  • leetcode 2239. 找到最接近 0 的数字
  • 深度剖析:AI Agent 与 RPA 融合的底层技术逻辑
  • python 组播udp诊断
  • 解锁C#编程新姿势:Z.ExtensionMethods入门秘籍
  • MySQL用户授权、收回权限与查看权限
  • AI知识库如何提升电子电器企业的运营效率
  • MVCC在MySQL中实现无锁的原理
  • C语言基础------练习
  • WordPress标签导入插件
  • 时间类型数据处理:基于Python的datetime库和pandas库
  • JVM之Java编译到执行(1)--引
  • 教育培训微信小程序ssm+论文源码调试讲解
  • CBAM-2018学习笔记
  • 如何使 LLaMA-Factory 支持 google/gemma-2-2b-jpn-it 的微调
  • 网络(二)协议
  • GIT的常规使用
  • 【MySQL — 数据库增删改查操作】深入解析MySQL的create insert 操作
  • docker 启动镜像命令集合
  • Java 大视界 -- Java 大数据中的异常检测技术与应用(61)
  • ESP8266 OTA固件启动日志里分区解析【2M flash】
  • 【Java实现 通过Easy Excel完成对excel文本数据的读写】