去 ffmpeg.org/download.ht… 下载源码
编译 ffmpeg
# ./configure -h 如果参数忘了可以通过这条命令查看
./configure --prefix=/Users/mac/ffmpeg-7.1.1 --disable-static --enable-shared --enable-debug=3
make -j 4
make install
如果编译时不禁用静态库,并且开启共享库,连接编译时会收获 101 个 undefined symbol 编译错误,如果上面照做了则不会,
'/Users/mac/ffmpeg-7.1.1/lib/libavutil.59.39.100.dylib' not valid for use in process: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed
这个是动态链接库签名错误。下面答案来自 deepseek。
==== 这个错误表明你的 FFmpeg 动态库(.dylib) 没有被正确签名,而 macOS(特别是较新版本如 macOS 10.15+)要求所有可执行文件和动态库必须经过 代码签名,即使是本地运行也需要 ad-hoc 签名(最低级别的签名)。
解决方法
1. 使用 codesign 进行 ad-hoc 签名
codesign -f -s - /Users/mac/ffmpeg-7.1.1/lib/libavutil.59.39.100.dylib
-f:强制覆盖现有签名-s -:使用 ad-hoc 签名(不依赖开发者证书)- 最后指定
.dylib文件路径
对所有 FFmpeg 动态库签名:
for lib in /Users/mac/ffmpeg-7.1.1/lib/*.dylib; do
codesign -f -s - "$lib"
done
2. 如果仍然报错:检查 SIP 和文件权限
-
确保 SIP(系统完整性保护)未阻止签名(默认开启,一般无需关闭)。
-
确保你有文件读写权限:
chmod +x /Users/mac/ffmpeg-7.1.1/lib/libavutil.59.39.100.dylib
3. 如果使用 Xcode 运行
-
在 Xcode 项目的
Build Phases里添加 Run Script,自动签名动态库:find "$CODESIGNING_FOLDER_PATH" -name "*.dylib" -exec codesign -f -s - {} ;
4. 其他可能的问题
-
动态库路径错误:检查
.dylib是否在正确位置。 -
FFmpeg 版本兼容性:尝试重新编译 FFmpeg(
--enable-shared确保生成正确的动态库)。 -
macOS 安全策略:如果仍然报错,尝试在终端运行:
sudo spctl --master-disable # 临时禁用 Gatekeeper(不推荐长期使用)
总结
- 必须签名:macOS 要求所有
.dylib文件至少要有 ad-hoc 签名。 - 推荐方法:使用
codesign -f -s -签名所有 FFmpeg 动态库。 - Xcode 集成:通过 Run Script 自动签名,避免手动操作。
如果问题仍然存在,可能是动态库损坏或编译问题,建议重新编译 FFmpeg 或检查依赖项。
====
This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSMicrophoneUsageDescription key with a string value explaining to the user how the app uses this data
1 设置 ffmpeg 动态库
2 设置沙盒
3 设置头文件搜索路径
创建 testc.c 文件
勾选 创建头文件
点击创建
第一次创建 c 语言文件会提示 是否创建桥接文件,点击创建
代码:
桥接文件
// myapp-Bridging-Header.h
#import "testc.h"
c 代码 文件头
// testc.h 头文件
#ifndef testc_h
#define testc_h
#include <stdio.h>
#include "libavutil/avutil.h"
#include "libavdevice/avdevice.h"
#include "libavformat/avformat.h"
void haha(void);
#endif /* testc_h */
其中下面的代码中 devicename 的值
// [[video device]:[audio device]]
char *devicename = ":2";
可以通过 下面的方式获取
➜ bin ./ffmpeg -f avfoundation -list_devices true -i ' '
ffmpeg version 7.1.1 Copyright (c) 2000-2025 the FFmpeg developers
built with Apple clang version 17.0.0 (clang-1700.0.13.5)
configuration: --prefix=/Users/mac/ffmpeg-7.1.1 --disable-static --enable-shared --enable-debug=3
libavutil 59. 39.100 / 59. 39.100
libavcodec 61. 19.101 / 61. 19.101
libavformat 61. 7.100 / 61. 7.100
libavdevice 61. 3.100 / 61. 3.100
libavfilter 10. 4.100 / 10. 4.100
libswscale 8. 3.100 / 8. 3.100
libswresample 5. 3.100 / 5. 3.100
2025-06-26 22:10:51.377 ffmpeg[2000:14415] WARNING: Add NSCameraUseContinuityCameraDeviceType to your Info.plist to use AVCaptureDeviceTypeContinuityCamera.
[AVFoundation indev @ 0x7fcbc7904ac0] AVFoundation video devices:
[AVFoundation indev @ 0x7fcbc7904ac0] [0] FaceTime HD Camera (Built-in)
[AVFoundation indev @ 0x7fcbc7904ac0] [1] OBS Virtual Camera
[AVFoundation indev @ 0x7fcbc7904ac0] [2] Capture screen 0
[AVFoundation indev @ 0x7fcbc7904ac0] AVFoundation audio devices:
[AVFoundation indev @ 0x7fcbc7904ac0] [0] MacBook Pro Microphone
[in#0 @ 0x7fcbc7904400] Error opening input: Input/output error
Error opening input file .
Error opening input files: Input/output error
c 代码文件体
// testc.c 文件体
//
// testc.c
// myapp
//
// Created by mac on 2025/6/23.
//
#include "testc.h"
void haha(void) {
int ret = 0;
char errors[1024];
AVFormatContext *fmt_ctx = NULL;
AVDictionary *options = NULL;
// [[video device]:[audio device]]
char *devicename = ":2";
// 1 register audio device
avdevice_register_all();
// 2 get format
// const AVInputFormat *iformat = av_find_input_format("avfoundation");
const AVInputFormat *i_format = av_find_input_format("avfoundation");
// 3 open device
ret = avformat_open_input(&fmt_ctx, devicename, i_format, &options);
if (ret < 0) {
av_strerror(ret, errors, 1024);
printf(stderr, "Failed to open audio device [%d] %s\n", ret, errors);
return;
}
printf("this is a c function\n");
av_log_set_level(AV_LOG_DEBUG);
av_log(NULL, AV_LOG_DEBUG, "hello world from av_log \n ");
return;
}
// ViewController.swift
//
// ViewController.swift
// myapp
//
// Created by mac on 2025/6/23.
//
import Cocoa
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.setFrameSize(NSSize(width: 320, height: 240))
let btn = NSButton.init(title: "Button", target: nil, action: nil)
btn.title = "Hello"
btn.frame = NSRect(x: 320 / 2 - 40, y: 240 / 2 - 15, width: 80, height: 30)
btn.bezelStyle = .rounded
btn.setButtonType(.pushOnPushOff)
// callback
btn.target = self
btn.action = #selector(myFunc)
self.view.addSubview(btn)
// Do any additional setup after loading the view.
}
@objc
func myFunc(){
// print("Hello World")
haha()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}