ffplay 嵌入
没成功:
方法 1:自己编译支持 -xid 的 ffmpeg(最彻底)
这个是开发者常用的方案,一劳永逸:
这个是开发者常用的方案,一劳永逸:sudo apt install build-essential yasm pkg-config libx11-dev libsdl2-dev libxext-dev libxv-dev
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg
./configure --enable-gpl --enable-sdl2 --enable-libx11 --enable-x11grab --enable-opengl --enable-libx264
make -j$(nproc)
sudo make install
#!/usr/bin/env bash
set -e
WORKDIR="$HOME/ffmpeg_build_x11"
mkdir -p "$WORKDIR"
cd "$WORKDIR"# 1) 安装基础依赖(Debian/Ubuntu / 麒麟 通用)
sudo apt update
sudo apt install -y \autoconf automake build-essential cmake git libtool pkg-config nasm yasm \libx11-dev libxext-dev libxv-dev libxi-dev libxinerama-dev libxrandr-dev \libsdl2-dev libgl1-mesa-dev libpulse-dev libavcodec-dev libavformat-dev \libswscale-dev libv4l-dev libdrm-dev libx264-dev libx265-dev libfreetype6-dev \libwebp-dev libvpx-dev libopus-dev libvorbis-dev libmp3lame-dev libass-dev \libfdk-aac-dev libnuma-dev# 可选:安装一些编码库的源码(略——如果你需要更多 codec,可单独编译)
# 2) 获取 ffmpeg 源码(最新版 stable 分支)
if [ ! -d ffmpeg ]; thengit clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
elsecd ffmpeggit pullcd ..
ficd ffmpeg# 为了保险,清理
make distclean || true# 3) 配置(启用 SDL2、X11、x11grab、opengl 等)
PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:/usr/lib/pkgconfig"
export PKG_CONFIG_PATH./configure \--prefix=/usr/local \--enable-gpl \--enable-nonfree \--enable-libx264 \--enable-libx265 \--enable-libvpx \--enable-libopus \--enable-libvorbis \--enable-libmp3lame \--enable-libfreetype \--enable-libwebp \--enable-libass \--enable-sdl2 \--enable-opengl \--enable-libdrm \--enable-x11grab \--enable-libx11 \--enable-shared \--disable-debug \--disable-static# 4) 编译与安装
make -j"$(nproc)"
sudo make install
sudo ldconfig# 5) 验证
echo "验证 ffplay 是否支持 -xid ..."
if ffplay -h 2>&1 | grep -q xid; thenecho "OK: ffplay 支持 -xid"
elseecho "警告: ffplay 未显示 -xid(可能编译环境还有缺失依赖)"
fiecho "完成。ffmpeg/ffplay 已安装到 /usr/local/bin"
sudo apt install xdotool x11-utils
屏幕会闪一下。
import subprocess
import sys
import time
import re
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QWindowclass FFplayEmbedHack(QWidget):def __init__(self, video_path):super().__init__()self.video_path = video_pathself.proc = Noneself.setWindowTitle("FFplay 伪嵌入版(麒麟系统 X11)")self.resize(800, 450)# 视频容器区域self.video_widget = QWidget(self)self.video_widget.setStyleSheet("background-color: black;")layout = QVBoxLayout(self)layout.addWidget(self.video_widget)self.btn = QPushButton("播放视频")layout.addWidget(self.btn)self.setLayout(layout)self.btn.clicked.connect(self.play_video)def play_video(self):if self.proc:print("视频已在播放。")return# 唯一标题,用于识别窗口self.unique_title = f"FFPLAY_{int(time.time())}"# 启动 ffplaycmd = ["ffplay","-window_title", self.unique_title,"-noborder","-loglevel", "quiet","-nostats","-autoexit",self.video_path]print("执行命令:", " ".join(cmd))self.proc = subprocess.Popen(cmd)# 延迟执行嵌入(等待 ffplay 窗口出现)QTimer.singleShot(800, self.try_embed_ffplay)def try_embed_ffplay(self):# 获取 ffplay 窗口 IDtry:out = subprocess.check_output(["xwininfo", "-name", self.unique_title], text=True)m = re.search(r"Window id: (0x[0-9a-f]+)", out)if not m:print("未找到 ffplay 窗口,稍后重试...")QTimer.singleShot(500, self.try_embed_ffplay)returnwid = m.group(1)except subprocess.CalledProcessError:print("ffplay 窗口未出现,重试中...")QTimer.singleShot(500, self.try_embed_ffplay)returnprint(f"🎬 找到 ffplay 窗口 ID: {wid}")# 获取 PyQt 子窗口 IDpyqt_wid = hex(int(self.video_widget.winId()))print(f"🎯 PyQt 容器窗口 ID: {pyqt_wid}")# 执行重父化命令subprocess.call(["xdotool", "windowreparent", wid, pyqt_wid])subprocess.call(["xdotool", "windowmove", wid, "0", "0"])subprocess.call(["xdotool", "windowsize", wid,str(self.video_widget.width()),str(self.video_widget.height())])print("✅ ffplay 已嵌入 PyQt 区域")# 定时同步大小QTimer.singleShot(500, lambda: self.adjust_ffplay_window(wid))def adjust_ffplay_window(self, wid):"""保持 ffplay 窗口与 PyQt 容器同步大小"""if self.proc and self.proc.poll() is None:subprocess.call(["xdotool", "windowsize", wid,str(self.video_widget.width()),str(self.video_widget.height())])QTimer.singleShot(500, lambda: self.adjust_ffplay_window(wid))def closeEvent(self, event):if self.proc:self.proc.terminate()event.accept()if __name__ == "__main__":app = QApplication(sys.argv)player = FFplayEmbedHack("/home/ykll/guozhan/download/prod-api/profile/2025/11/04/20ecd2f9e6704712bceefc77833c1f1b.mp4")player.show()sys.exit(app.exec_())
