ffmpeg + gstreamer: 投屏如此简单

FFmpeg+GStreamer实现简易投屏

在这里插入图片描述
在这里插入图片描述

契机

前段时间研究OpenIPC 的过程突发奇想, 能不能简单用FFMEPG + GStreamer 实现简单的投屏功能, 实际测试可行并且效果还不错.

FFmpeg和GStreamer

FFmpeg和GStreamer都是处理音视频的核心工具,但定位不同,FFmpeg侧重命令行工具与基础库,GStreamer侧重灵活的管线式开发框架。

1. FFmpeg:音视频处理的“瑞士军刀”

FFmpeg是一套跨平台的音视频处理工具集,包含命令行工具和开发库,是行业内的基础组件。

  • 核心能力:支持几乎所有音视频格式的编解码、转换、剪辑、封装和解封装。
  • 典型用途:通过命令行快速完成格式转换(如MP4转MKV)、视频剪辑、提取音频等操作;开发者可调用其核心库(如libavcodec、libavformat)搭建音视频功能。
  • 特点:轻量高效,专注于“处理”本身,命令行操作简洁直接,适合快速任务或作为其他软件的底层依赖。

2. GStreamer:灵活的音视频“管线框架”

GStreamer是一个用于构建音视频流应用的开发框架,核心是“管线(Pipeline)”概念,通过组合不同插件实现复杂功能。

  • 核心能力:支持音视频的采集、编码、传输、播放、编辑等全流程处理,插件生态丰富。
  • 典型用途:开发需要自定义流程的音视频应用,如直播推流软件、视频监控系统、媒体播放器等;可灵活组合插件(如“摄像头采集→H.264编码→RTMP推流”)。
  • 特点:侧重“框架”,适合复杂场景的开发,学习成本较高,但灵活性极强,支持多语言绑定(C、Python、Rust等)。

两者核心差异对比

维度FFmpegGStreamer
定位工具集 + 基础库开发框架
核心优势命令行高效处理,库轻量通用插件化管线,灵活应对复杂场景
适用场景快速任务处理、作为底层依赖库自定义音视频应用开发
学习成本命令行简单,库开发中等框架概念复杂,学习成本较高

WIndows 10 投屏

FFMPEG
下载: FFMPEG Download
解压后配置下环境变量即可使用

指定分辨率

ffmpeg -f gdigrab -video_size 1280x720 -framerate 30 -i desktop ^
-vcodec libx264 -preset ultrafast -tune zerolatency -crf 25 ^
-profile:v high -pix_fmt yuv420p ^
-f rtp rtp://192.168.4.16:5600 

可选: 生成SDP

ffmpeg -f gdigrab -framerate 30 -i desktop ^
-vcodec libx264 -preset ultrafast -tune zerolatency -crf 25 ^
-profile:v high -pix_fmt yuv420p ^
-f rtp rtp://192.168.4.16:5600 ^
-sdp_file screen.sdp

关键: -sdp_file screen.sdp

Ubuntu 接收播放端

方式1: 使用底层管线方式, 不需要SDP文件

# 使用底层管线方式, 不需要SDP文件
gst-launch-1.0 -v udpsrc port=5600 \
caps="application/x-rtp, encoding-name=H264, payload=96" \
! rtph264depay ! h264parse ! avdec_h264 ! videoconvert \
! autovideosink sync=false

方式2: 使用SDP

# 使用SDP
gst-launch-1.0 -v \
filesrc location=/home/xxx/Downloads/screen-3.sdp ! sdpdemux name=demux \
demux. ! queue max-size-buffers=10 max-size-time=0 ! rtph264depay ! \
h264parse config-interval=1 ! \
avdec_h264 ! queue max-size-buffers=2 leaky=downstream ! \
videoconvert ! \
autovideosink sync=false

在这里插入图片描述

实际测试 1280x720 结果: 局域网中视频流畅, 延迟1帧 (0-30 毫秒)

碰到的一些问题

播放报错

	gst-launch-1.0 -v \
	filesrc location=/home/xxx/Downloads/screen-3.sdp ! sdpdemux name=demux \
	demux. ! queue max-size-buffers=10 max-size-time=0 ! rtph264depay ! \
	h264parse config-interval=1 ! \
	avdec_h264 ! queue max-size-buffers=2 leaky=downstream ! \
	autovideosink sync=false

报错

/GstPipeline:pipeline0/avdec_h264:avdec_h264-0.GstPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40032ffe1001967f400329196802800b5a10000030001000003003c8f1832a001000568ce1c6480, level=(string)5, profile=(string)high-4:4:4, width=(int)2560, height=(int)1440, framerate=(fraction)30/1, chroma-format=(string)4:4:4, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, parsed=(boolean)true
/GstPipeline:pipeline0/GstH264Parse:h264parse0.GstPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40032ffe1001967f400329196802800b5a10000030001000003003c8f1832a001000568ce1c6480, level=(string)5, profile=(string)high-4:4:4
/GstPipeline:pipeline0/avdec_h264:avdec_h264-0.GstPad:src: caps = video/x-raw, format=(string)Y444, width=(int)2560, height=(int)1440, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, chroma-site=(string)mpeg2, framerate=(fraction)30/1
Redistribute latency...
ERROR: from element /GstPipeline:pipeline0/GstSDPDemux:demux/GstUDPSrc:udpsrc0: Internal data stream error.
Additional debug info:
../libs/gst/base/gstbasesrc.c(3127): gst_base_src_loop (): /GstPipeline:pipeline0/GstSDPDemux:demux/GstUDPSrc:udpsrc0:
streaming stopped, reason not-negotiated (-4)
Execution ended after 0:00:07.612576676
Setting pipeline to NULL ...
Freeing pipeline ...

原因
核心问题是 “流协商失败(not-negotiated)”,通常是因为GStreamer管道中某个元素的格式(caps)不匹配,具体与H.264的编码格式(high-4:4:4)和硬件解码器的支持范围有关。

关键错误分析:

日志中显示H.264流的编码参数为:

profile=(string)high-4:4:4, chroma-format=(string)4:4:4
  • high-4:4:4 是H.264的高规格Profile,且采用 4:4:4色度采样(通常用于高质量视频,如专业监控)。
  • 显卡硬件解码器(dec)或渲染器(sink)可能不支持这种格式,导致格式协商失败。

解决方案:强制转换格式或改用软件解码

方案1:强制转换格式或改用软件解码
gst-launch-1.0 -v \
filesrc location=screen.sdp ! sdpdemux name=demux \
demux. ! queue max-size-buffers=10 ! rtph264depay ! h264parse config-interval=1 ! \
avdec_h264 ! \
queue ! videoconvert !  \
autovideosink sync=false
  • 关键:转换色彩格式,适配渲染器, videoconvert 转换为渲染器支持的格式(如4:2:0)。
方案2:修改ffmpeg推流参数(从源头避免4:4:4)

最彻底的方式是让ffmpeg输出硬件解码器友好的格式(如high Profile + 4:2:0采样),修改推流命令:

ffmpeg -f gdigrab -framerate 30 -i desktop ^
-vcodec libx264 -preset ultrafast -tune zerolatency -crf 25 ^
-profile:v high -pix_fmt yuv420p ^ 
-f rtp rtp://192.168.4.16:5600 ^
-sdp_file screen.sdp
  • 关键: -profile:v high -pix_fmt yuv420p 强制用4:2:0采样和high profile

Ubuntu 投屏与接收

# 发送
ffmpeg -f x11grab -framerate 30 -video_size 1920x1080 -i :1 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-f rtp rtp://192.168.7.121:5600

## 接收
gst-launch-1.0 -v udpsrc port=5000 caps="application/x-rtp, media=video, encoding-name=H264, payload=96" ! rtph264depay ! queue max-size-buffers=1 leaky=downstream ! avdec_h264 ! videoconvert ! autovideosink

videoconvert: 会把 Y444 转成显示器能用的格式(通常 RGB 或 YUV420)。解决收到包, 不显示问题

报错:

  libpostproc    55.  5.100 / 55.  5.100
Invalid MIT-MAGIC-COOKIE-1 key[x11grab @ 0x56423666e300] Cannot open display :0.0, error 1.
:0.0: Input/output error
$ echo $DISPLAY
:1

原来: ffmpeg -f x11grab -framerate 30 -video_size 1920x1080 -i :0.0
改为: ffmpeg -f x11grab -framerate 30 -video_size 1920x1080 -i :1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值