诊断程序:查明冲突

这里我遇到的问题是这个:ffmpeg: symbol lookup error: ffmpeg: undefined symbol: avio_protocol_get_class, version LIBAVFORMAT_58

那么接下来就针对这个问题给出常用的排查以及解决方案:

表 1:常见诊断命令和问题指示器

命令

目的

关键输出(问题指示器)

which ffmpeg

确认 ffmpeg 可执行文件的路径。

/usr/local/bin/ffmpeg (手动安装,可能与系统库冲突)

ffmpeg -version

显示 FFmpeg 版本及其内置库版本。

报告的 libavformat 版本与实际加载的版本不一致,或显示非预期的构建信息。

ldd $(which ffmpeg)

列出 ffmpeg 依赖的所有共享库及其加载路径。

libavformat.so.58 => /usr/local/lib/libavformat.so.58 (加载了非系统路径的库),或 not found (库文件缺失)。

apt-cache policy ffmpeg

显示 apt 包管理器中 ffmpeg 包的安装状态和可用版本。

存在多个版本,或安装的版本来自非预期仓库,或显示“候选版本”与“已安装版本”不匹配。

apt-cache policy libavformat58

显示 libavformat58 包的安装状态和可用版本。

ffmpeg 类似的冲突迹象。

echo $LD_LIBRARY_PATH

检查 LD_LIBRARY_PATH 环境变量的设置。

包含非标准或不正确的库路径,可能导致加载错误的库。

sudo ldconfig -p | grep libavformat

打印动态链接器缓存中已知的 libavformat 库。

显示多个 libavformat.so.58 条目,或缺少预期版本。

sudo find / -name "libavformat.so.*"

在文件系统中查找所有 libavformat 库文件。

发现多个 libavformat.so.58 文件存在于不同路径,表明存在冗余或冲突的安装。

我这里按照上述 which ffmpegldd $(which ffmpeg) 输出信息,它们明确指出了问题的根源

  1. which ffmpeg 输出 /usr/local/bin/ffmpeg: 这证实了ffmpeg 可执行文件是手动安装或从第三方编译的,而不是通过 Ubuntu 的 apt 包管理器安装的 。在 Linux 系统中,  

    /usr/local/bin 通常用于存放用户或管理员手动安装的程序,这与系统包管理器管理的 /usr/bin 路径不同。

  2. ldd $(which ffmpeg) 输出 libavformat.so.58 => /lib/aarch64-linux-gnu/libavformat.so.58: 这表明手动安装的 ffmpeg 可执行文件在运行时,正在尝试加载系统默认路径 /lib/aarch64-linux-gnu/ 下的 libavformat.so.58 库 。  

问题分析:

综合这两点和之前 apt-cache policy libavformat58 的输出(显示 libavformat58 版本为 7:4.2.7-0ubuntu0.1),可以确定遇到的错误是典型的应用程序二进制接口(ABI)不兼容问题。

手动安装的 ffmpeg 二进制文件很可能是在一个特定版本的 libavformat.so.58 环境下编译的。然而,在运行时,它加载的是您系统上通过 apt 安装的 libavformat58 库(版本 7:4.2.7-0ubuntu0.1)。尽管这两个库都声称是“版本 58”,但它们在内部的函数签名、数据结构或符号定义上可能存在细微差异。这种差异导致 ffmpeg 在尝试调用 avio_protocol_get_class 这个符号时,无法在当前加载的 libavformat.so.58 中找到完全匹配的定义,从而引发了“未定义符号”错误 。  

解决 FFmpeg 库冲突的综合方案

移除冲突的 FFmpeg 安装

在尝试任何新的安装之前,务必彻底移除所有可能冲突的 FFmpeg 包,以防止残留文件导致新问题。

  • 对于 apt 安装的 FFmpeg:执行 sudo apt-get remove --purge ffmpeg,然后执行 sudo apt-get autoremove--purge 选项确保也移除配置文件 。  

  • 对于手动编译的 FFmpeg:如果 which ffmpeg 指向 /usr/local/bin/ffmpeg ,则需要手动从  

    /usr/local/bin/usr/local/lib(或其安装时指定的 --prefix 路径)移除 ffmpeg 二进制文件及其相关库。这通常涉及 sudo rm -rf /usr/local/bin/ffmpeg /usr/local/lib/libav*,但操作时务必极其小心,避免删除不相关的文件。

安装 NVIDIA 提供的 Jetson FFmpeg 包

对于 NVIDIA Jetson 平台,这通常是最可靠和推荐的解决方案,因为这些包由 NVIDIA 专门编译和优化,以与其硬件视频加速库和 JetPack 环境协同工作。

  • 命令sudo apt install ffmpeg=7:4.2.2-nvidia.1。请注意,确切的版本 7:4.2.2-nvidia.1 是特定于 L4T r32.7 的 。用户应根据其具体的 JetPack/L4T 版本在 NVIDIA 开发者论坛上验证正确的版本。  

  • 原因:使用 NVIDIA 的官方包可最大程度地减少与其专有驱动程序和硬件加速组件之间的 ABI 兼容性问题,这对于 Jetson 上的性能至关重要 。  

    鉴于用户在 NVIDIA Jetson Xavier NX 上遇到的特定挑战,以及 apt 安装在 Jetson 上因依赖问题而失败的现象 ,NVIDIA 提供的特定版本 FFmpeg 包(  

    ffmpeg=7:4.2.2-nvidia.1)是首选解决方案。在像 Jetson 这样的专业嵌入式平台上,供应商提供的软件堆栈通常是最稳定和高性能的,因为它针对专有驱动和硬件加速库进行了构建和测试。因此,这应是首要推荐的解决方案,它直接解决了诊断阶段识别出的平台特定挑战,提供了一条可能兼容并利用硬件能力的解决路径,从而绕过了通用 Ubuntu 构建的复杂性及潜在冲突。

利用社区 PPA(例如 Savoury1 的 FFmpeg 4 PPA)用于 Ubuntu 20.04

如果 NVIDIA 提供的 FFmpeg 版本过旧或缺少用户所需的特定功能,维护良好的社区 PPA 可以为 Ubuntu 20.04 提供更最新、功能更丰富的 FFmpeg 4.4.6。

  • 命令

    Bash

    sudo add-apt-repository ppa:savoury1/ffmpeg4
    sudo apt update
    sudo apt-get upgrade && sudo apt-get dist-upgrade # 对依赖解析至关重要
    sudo apt-get install ffmpeg
    
  • 注意事项:Savoury1 的 PPA 通常需要对其他核心多媒体库(例如 GStreamer、PipeWire、GLib)进行大量升级以确保兼容性 。尽管这些升级通常设计为向后兼容,但它们仍可能引入与系统其他组件或应用程序之间意想不到的交互。因此,应谨慎使用此方法,并在操作前备份关键系统数据。  

apt 包管理最佳实践

  • 在安装或升级包之前,始终运行 sudo apt update 以刷新包列表。

  • 使用 apt-cache policy <package_name> 检查来自不同仓库的可用版本并了解其来源。

  • 优先选择官方 Ubuntu 仓库或受信任、维护良好的 PPA。避免添加过多 PPA,因为这会增加依赖冲突的风险。

 

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐