You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Expo裸工作流iOS应用集成ffmpegkit.framework遇问题求助

解决FFmpegKit手动集成到React Native Expo裸工作流的两个核心问题

一、先修复构建循环错误(Cycle inside SoundBud)

这个问题源于框架被重复添加到复制阶段,或存放路径触发Xcode构建依赖冲突:

  1. 移除重复的Embed配置
    你已通过「Frameworks, Libraries and Embedded Content」设置了「Embed and Sign」,这会自动在「Build Phases」的「Embed Frameworks」中生成条目。请删除步骤6中手动添加的ffmpegkit.framework条目,避免重复复制操作。

  2. 调整框架存放路径
    不要将ffmpegkit.framework放在项目的Frameworks目录(projectDir/ios/Frameworks),建议移到ios目录下的独立文件夹,比如ios/ThirdParty/ffmpegkit.framework。这能避免Xcode将其识别为项目内部框架,引发构建循环。

  3. 清理冗余的Copy Files阶段
    检查「Build Phases」中是否有其他Copy Files阶段包含ffmpegkit.framework,如有则直接移除。

二、修复Swift提示「No such module 'ffmpegkit'」

该问题通常由模块名不匹配、桥接配置缺失或搜索路径错误导致:

  1. 修正模块导入的大小写
    FFmpegKit的Swift模块名通常为FFmpegKit(首字母大写),而非全小写的ffmpegkit。修改Swift代码的导入语句:

    import Foundation
    import FFmpegKit // 替换原import ffmpegkit
    import React
    
  2. 配置桥接文件
    在SoundBud-Bridging-Header.h中添加FFmpegKit的头文件导入,确保Swift能识别框架的Objective-C接口:

    #import <ffmpegkit/FFmpegKit.h>
    #import <ffmpegkit/FFprobeKit.h>
    

    同时检查项目Target的「Build Settings」→「Swift Compiler - General」→「Objective-C Bridging Header」是否正确指向该文件,路径格式示例:$(PROJECT_DIR)/SoundBud-Bridging-Header.h(按实际文件名调整)。

  3. 验证Framework Search Paths
    确保路径指向框架的实际存放位置,比如框架放在ios/ThirdParty,则设置:

    • 路径值:"$(PROJECT_DIR)/ThirdParty"
    • 勾选「Recursive」
      注意:需在Target的Build Settings中设置,而非Project全局设置。
  4. 清理构建缓存

    • 执行Cmd + Shift + K清理项目构建缓存
    • 删除Derived Data:打开Xcode → 偏好设置 → 位置 → Derived Data,点击箭头打开文件夹,删除当前项目的缓存目录
    • 重启Xcode后重新构建
  5. 检查框架完整性
    确认下载的FFmpegKit LTS版本包含iOS所需架构:
    打开终端,进入框架目录,执行:

    lipo -info ffmpegkit.framework/ffmpegkit
    

    输出应包含arm64(真机)和x86_64(模拟器)架构,若缺失则重新下载对应iOS版本的框架。

调整后的Swift模块代码示例

import Foundation
import FFmpegKit
import React

@objc(FFmpegModule)
class FFmpegModule: NSObject, RCTBridgeModule {

    static func moduleName() -> String {
        return "FFmpegModule"
    }

    @objc
    func runCommand(_ command: String, resolver resolve: @escaping RCTPromiseResolveBlock, 
                    rejecter reject: @escaping RCTPromiseRejectBlock) {
        FFmpegKit.executeAsync(command) { session in
            let returnCode = session?.getReturnCode()
            resolve(returnCode?.getValue())
        }
    }

    @objc
    static func requiresMainQueueSetup() -> Bool {
        return false
    }
}

内容的提问来源于stack exchange,提问作者Alpi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:25:16