Linux:通过网络捕获屏幕桌面视频和 VNC 帧速率

发布于 2024-10-05 06:16:07 字数 11877 浏览 6 评论 0原文

抱歉,文字墙太长了 - TL;DR:

  • VNC 连接的帧速率是多少(以帧/秒为单位) - 或者更确切地说,由谁决定:客户端还是服务器?
  • 对于桌面屏幕捕获的任何其他建议 - 但“正确的时间编码”/具有不抖动的帧速率(具有稳定的周期);并有可能将其作为未压缩(或无损)图像序列获得?

简而言之 - 我遇到了一个典型的问题:我有时会开发硬件,并且想要录制一个视频来显示在 PC 上输入的两个命令(“桌面捕获”), 硬件的响应(“实时视频”)。在介绍具体细节之前,先进行一段介绍。  
 

简介/上下文

目前我的策略是使用摄像机记录硬件测试过程(作为“实时”视频),同时进行桌面捕获。摄像机生成 29.97 (30) FPS MPEG-2 .AVI 视频;我想以与视频相同的帧速率将桌面捕获为 PNG 图像序列。那么,这个想法就是:如果两个视频的帧速率相同;然后我可以简单地将

  • 桌面捕获的开始时间与“实时”视频中的匹配点对齐
  • 设置 画中画,将桌面捕获的缩小版本作为叠加层放置在“实时”视频之上
    • (“实时”视频的屏幕部分用作与“桌面捕获”叠加层的视觉同步源)
  • 导出“最终”组合视频,为互联网进行适当压缩

原则上,我想可以使用像 ffmpeg 这样的命令行工具来完成此过程;但是我更喜欢使用 GUI 来查找两个视频的对齐起点。

最终,我还想实现的是,在导出“最终”视频时保持最高质量:“实时”视频在离开相机时已经被压缩,这意味着当它通过 Theora .ogv 编解码器时会出现额外的降级 -这就是为什么我想保留原始视频,并使用命令行之类的东西重新生成“最终”视频(如果需要不同的压缩/分辨率)。这也是为什么我喜欢将“桌面捕获”视频作为 PNG 序列(尽管我猜任何未压缩的格式都可以):我采取措施“调整”桌面,因此没有太多渐变和无损编码(即PNG)是合适的。  
 

桌面捕获选项

好吧,在我目前使用的 Ubuntu Lucid 下,这个过程有很多麻烦(你可以在 10.04:使用 Theora ogv 进行视频叠加/合成编辑 - Ubuntu 论坛)。然而,关键问题之一是假设两个传入视频的帧速率相等 - 实际上,通常桌面捕获的帧速率较低;更糟糕的是,帧常常不同步

那么,这需要坐在视频编辑器前,在帧级别上手动剪切和编辑不到一秒的剪辑 - 需要几个小时的工作来完成将要出现在视频中的内容。结束 5 分钟的视频。另一方面,如果两个视频(“实时”和“捕获”)确实具有相同的帧速率和同步:原则上,您不需要超过几分钟的时间来找到在视频编辑器中启动同步点 - 其余的“合并”视频处理可以通过单个命令行来处理。这就是为什么在这篇文章中,我想重点关注桌面捕获部分。

据我所知,只有少数可行(而不是5对 Linux 桌面进行截屏的方法)在 Linux / Ubuntu 中进行桌面捕获的替代方案(注意,我通常使用笔记本电脑作为桌面捕获的目标):

  1. 让您的目标 PC(笔记本电脑)在其 VGA 输出上克隆桌面;使用 VGA 转复合或 VGA 转 S 视频硬件从 VGA 获取视频信号;在另一台 PC 上使用视频采集卡来抓取视频
  2. 在目标 PC 上使用 recordMyDesktop
  3. 设置 < a href="http://bobpeers.com/linux/vnc" rel="noreferrer">VNC 服务器 (vi 在 Ubuntu 上;或 vncserver)被捕获;在另一台 PC 上使用 VNC 捕获软件(例如 vncrec)进行抓取/录制VNC 流(随后可以转换为视频)。
  4. 使用 ffmpegx11grab 选项
  5. *(在目标 PC 上使用一些工具,这将执行 DMA 直接传输桌面图像帧 - 从显卡帧缓冲内存到网络适配器内存

请注意上述内容的用处方法受到我的使用环境的限制:我想要捕获的目标 PC 通常运行移动大量数据的软件(利用测试的硬件);关于描述这样一个系统,你最好的说法是“勉强稳定”:)我猜这与游戏玩家在想要获得要求较高的游戏的视频捕获时所面临的问题类似。一旦我开始使用像 recordMyDesktop 这样的东西,它也使用相当多的资源并且想要在本地硬盘上捕获 - 我立即遇到严重的内核崩溃(通常没有生成 vmcore)。

因此,在我的上下文中,我通常会假设有第二台计算机参与 - 运行“目标”PC 桌面的捕获和记录。除此之外,到目前为止我所看到的上述选项的优缺点如下。

(桌面准备)

对于下面讨论的所有方法,我倾向于事先“准备”桌面:

...以便最大限度地减少桌面捕获软件的负载。请注意,在 Ubuntu 上更改颜色深度需要更改 xorg.conf;但是,“在 /etc/X11 (Ubuntu 10.04) 中找不到 xorg.conf )” - 因此您可能需要先运行 sudo Xorg -configure 。

为了保持较低的图形资源使用率,我通常还禁用 compiz - 或者更确切地说,我将“系统/首选项/外观/视觉效果”设置为“无”。但是,在我尝试通过将“视觉效果”设置为“正常”来启用 compiz 后(未保存),我可以注意到 LCD 屏幕上的窗口重绘速度要快得多;所以我就这样保留它,也用于桌面捕获。我觉得这有点奇怪:更多效果如何导致屏幕刷新更快?它看起来不像是由于专有驱动程序造成的(该卡是“Intel Corporation N10 Family Integrated Graphics Controller”,并且 Ubuntu 在切换到 compiz< 时没有提供专有驱动程序选项/code>) - 不过,所有的模糊和效果可能只是欺骗了我的眼睛:) )。

克隆 VGA

嗯,这是最昂贵的选项(因为它需要额外购买不仅仅是一个,而是两个硬件:VGA 转换器和视频采集卡);主要适用于笔记本电脑(具有屏幕+额外的 VGA 输出 - 对于台式机,可能还需要投资额外的显卡或 VGA 克隆硬件)。

然而,它也是唯一不需要目标 PC 任何额外软件的选项(因此使用目标 CPU 的 0% 处理能力) - 并且也是唯一能够提供具有true,无抖动帧速率为 30 fps(因为它是由单独的硬件执行的 - 尽管假设各个硬件之间存在的时钟域未对准可以忽略不计)。

实际上,由于我已经拥有像采集卡这样的东西,所以我已经投资了 VGA 转换器 - 期望它最终能让我制作最终的“合并”视频,只需 5 分钟寻找对齐点和一个命令线;但我还不清楚这个过程是否会按预期进行。我还想知道如何以 800x600、30 fps 的速度将桌面捕获为未压缩视频。

recordMyDesktop

好吧,如果您在没有任何参数的情况下运行 recordMyDesktop - 它首先会在 /tmp/rMD-session-7247 等文件夹中捕获(看起来像)原始图像数据>;当您按 Ctrl-C 中断它后,它会将原始图像数据编码为 .ogv。显然,在与我的测试软件相同的硬盘上抓取大量图像数据(它也会移动大量数据)通常会导致 instacrash :)

因此,我尝试做的是 设置 Samba 以在网络上共享驱动器;然后在目标 PC 上,我将连接到此驱动器 - 并指示 recordMyDesktop 使用此网络驱动器(通过 gvfs) 作为其临时文件位置:

recordmydesktop --workdir /home/user/.gvfs/test\ on\ 192.168.1.100/capture/ --no-sound --quick-subsampling --fps 30 --overwrite -o capture.ogv 

请注意,虽然此命令将使用网络位置作为临时文件文件(从而使 recordMyDesktop 能够与我的软件并行运行) - 一旦您按下 Ctrl-C,它将开始编码并保存 capture.ogv直接在目标的本地硬盘驱动器上(不过,在这一点上,我并不真正关心:))

我对 recordMyDesktop 的第一个抱怨是你不能指示它保留临时文件,并避免对它们进行编码:您可以使用 Ctrl+Alt+p 暂停 - 或者您可以在第一个之后快速按 Ctrl-C,导致其崩溃;然后将留下临时文件(如果您第二次没有足够快地按下 Ctrl-C,程序将“清理缓存...”)。然后您可以运行,例如:

recordmydesktop --rescue /home/user/.gvfs/test\ on\ 192.168.1.100/capture/rMD-session-7247/

...以转换原始临时数据。然而,通常情况下,recordMyDesktop 本身会在执行此“救援”过程中出现段错误。尽管如此,我想保留临时文件的原因是为了拥有画中画蒙太奇的未压缩源。请注意,“--on-the-fly-encoding”将完全避免使用临时文件 - 代价是使用更多的 CPU 处理能力(对我来说,这又是导致崩溃的原因。)

然后是帧速率 - 显然,您可以使用“--fps N”选项设置请求的帧速率;但是,这并不能保证您实际上会获得该帧速率;例如,我会得到:

recordmydesktop --fps 25
...
Saved 2983 frames in a total of 6023 requests
...

...在我的测试软件运行时进行捕获;这意味着实际实现的速率更像是 25*2983/6032 = 12.3632 fps!

显然,帧被丢弃 - 大部分显示为视频播放速度太快。但是,如果我将请求的 fps 降低到 12,那么根据保存/总报告,我会达到 11 fps 之类的值;在这种情况下,视频播放看起来并没有“加速”。而且我还没有尝试将这样的捕获与实时视频对齐 - 所以我不知道那些实际保存的帧是否也有准确的时间戳。

VNC 捕获

对我来说,VNC 捕获包括在“目标”PC 上运行 VNC 服务器,并在“记录器”PC 上运行 vncrec(twibright 版本)。作为VNC服务器,我使用vino,即“系统/首选项/远程桌面(首选项)”。显然,即使 vino 配置 可能不是最容易管理的事情,vino 作为服务器似乎对“目标”PC 来说并不太费劲;因为当它与我的测试软件并行运行时,我没有遇到崩溃。

另一方面,当 vncrec 在“记录器”PC 上进行捕获时,它还会弹出一个窗口,向您显示“实时”中看到的“目标”桌面;当“目标”上有大量更新(即整个窗口移动)时,人们可以非常明显地看到“记录器”上的更新/刷新率问题。但是,对于小的更新(即只是光标在静态背景上移动),一切似乎都还不错。

这让我想知道我在这篇文章中的主要问题之一 - 设置 VNC 连接中的帧速率的是什么?

我还没有找到明确的答案,但从一些信息(参见下面的参考)中,我了解到:

  • VNC 服务器只是以最快的速度发送更改(屏幕更改+点击等)当它收到它们时,尽其所能;受服务器可用的最大网络带宽的限制
  • VNC 客户端接收那些因网络连接而延迟和抖动的更改事件,并尝试重建桌面“视频”流,再次尽可能快

......这意味着,人们无法用稳定的、周期性的帧速率(如视频)来描述任何事情。

vncrec 作为客户端而言,我得到的最终视频通常被声明为 10 fps,尽管帧可能会相当移位/抖动(这需要在视频编辑器中进行剪切)。请注意,vncrec-twibright/README 指出:“采样率电影的默认值为 10 或由 VNCREC_MOVIE_FRAMERATE 环境变量覆盖,如果未指定则为 10。";但是,联机帮助页还指出“VNCREC_MOVIE_FRAMERATE - 指定输出影片的帧速率。仅在 -movie 模式下有效。默认为 10。当您的转码器从 10 开始呕吐时,请尝试 2​​4。”。如果查看“vncrec/sockets.c”源代码,可以看到:

void print_movie_frames_up_to_time(struct timeval tv)
{
  static double framerate;
  ....
  memcpy(out, bufoutptr, buffered);
  if (appData.record)
    {
      writeLogHeader (); /* Writes the timestamp */
      fwrite (bufoutptr, 1, buffered, vncLog);
    }

...这表明写入了一些时间戳 - 但这些时间戳是否源自“原始”“目标”PC ,还是“录音机”,我不知道。 编辑:感谢@kanaka的回答,我检查了 vncrec/sockets.c,可以看到是writeLogHeader函数本身调用了gettimeofday;因此它写入的时间戳是本地的 - 也就是说,它们源自“记录器”PC(因此,这些时间戳不能准确描述帧何时源自“目标”PC)。

无论如何,在我看来,服务器发送 - 和 vncrec 作为客户端接收 - 每当;并且只有在随后从原始捕获对视频文件进行编码的过程中,才会设置/插值某种形式的帧速率。

我还想指出,在我的“目标”笔记本电脑上,有线网络连接已损坏;因此,无线是我访问路由器和本地网络的唯一选择 - 速度远低于路由器通过有线连接处理的 100MB/s。但是,如果捕获帧中的抖动是由“目标”PC 上的负载导致的错误时间戳引起的,我认为良好的网络带宽不会有太大帮助。

最后,就 VNC 而言,还可以尝试其他替代方案 - 例如 VNCast 服务器(有前途,但需要一些时间从源代码构建,并且处于“早期实验版本”);或MultiVNC(尽管,它看起来只是一个客户端/查看器,没有录制选项)。

ffmpeg 与 x11grab

还没有玩过这么多,但是,我已经尝试过与 netcat 结合使用; this:

# 'target'
ffmpeg -f x11grab -b 8000k -r 30 -s 800x600 -i :0.0 -f rawvideo - | nc 192.168.1.100 5678
# 'recorder'
nc -l 0.0.0.0 5678 > raw.video  #

... 确实捕获了一个文件,但是 ffplay 无法正确读取捕获的文件; while:

# 'target'
ffmpeg -f x11grab -b 500k -r 30 -s 800x600 -i :0.0 -f yuv4mpegpipe -pix_fmt yuv444p - | nc 192.168.1.100 5678
# 'recorder'
nc -l 0.0.0.0 5678 | ffmpeg -i - /path/to/samplimg%03d.png

确实生成 .png 图像 - 但有压缩伪影(我猜是 yuv4mpegpipe 涉及的压缩结果)。

因此,我目前不太喜欢 ffmpeg+x11grab - 但也许我只是不知道如何根据我的需要进行设置。

*(显卡 -> DMA -> 网络)

诚然,我不确定是否存在这样的东西 - 事实上,我打赌它不存在:)而且我不是这里的专家,但我推测:

如果DMA 内存传输可以从图形卡(或其保存当前桌面位图的缓冲区)作为启动,网络适配器作为目标 - 那么原则上,它应该可以获得具有正确(且合适)帧速率的未压缩桌面捕获。当然,使用 DMA 传输的目的是减轻处理器将桌面映像复制到网络接口的任务(因此,减少捕获软件对运行在“计算机”上的进程的影响)目标 PC - 尤其是那些处理 RAM 或硬盘的 PC)。

当然,这样的建议假设:有大量的网络带宽(对于 800x600、30 fps 至少 800*600*3*30 = 43200000 bps = 42 MiB/s,这对于本地 100 MB/s 网络);另一台进行“记录”的 PC 上有足够的硬盘 - 最后,软件可以随后读取原始数据,并基于它生成图像序列或视频:)

我可以忍受的带宽和硬盘需求 - 作为只要保证稳定的帧率和未压缩的数据即可;这就是为什么我很想听听这样的事情是否已经存在。

———————— 

好吧,我想就是这样 - 我能说的尽可能简短:) 对工具或流程的任何建议,可以以

  • 未压缩格式进行桌面捕获(最终可转换为未压缩/无损 PNG 图像序列),并
  • 具有“正确的时间编码”、稳定的帧速率

......,最终将有助于“简单”、单个命令行处理来生成“画中画”叠加视频 - 将不胜感激!

预先感谢您的任何评论,
干杯!


参考文献

  1. 在 Linux 上为 CryptoTE 制作截屏视频的经验 -idlebox.net
  2. VideoLAN 论坛 • 查看主题 - VNC 客户端输入支持(例如screen://)
  3. VNCServer 限制慢速客户端的用户输入 - Kyprianou,马克 - com.realvnc.vnc-list - MarkMail
  4. Linux 常见问题 - X Windows:如何使用 VNC 显示和控制远程桌面
  5. 需要多少带宽需要 VNC 吗? RealVNC - 常见问题
  6. x11vnc:用于真实 X 显示器的 VNC 服务器
  7. < a href="http://wiki.debian.org/HowtoRecordVNC" rel="noreferrer">HowtoRecordVNC(X11 会话)- Debian Wiki
  8. Ubuntu 中 gtk-RecordMyDesktop 的替代方案
  9. (Ffmpeg-user) 如何在 ffmpeg 中使用管道
  10. (ffmpeg-devel) (PATCH) 修复在不支持 XFixes 扩展的 Xserver 上绘制光标时 x11grab 中的段错误

Sorry for the wall of text - TL;DR:

  • What is the framerate of VNC connection (in frames/sec) - or rather, who determines it: client or server?
  • Any other suggestions for desktop screen capture - but "correctly timecoded"/ with unjittered framerate (with a stable period); and with possibility to obtain it as uncompressed (or lossless) image sequence?

Briefly - I have a typical problem that I am faced with: I sometimes develop hardware, and want to record a video that shows both commands entered on the PC ('desktop capture'), and responses of the hardware ('live video'). A chunk of an intro follows, before I get to the specific detail(s).
 
 

Intro/Context

My strategy, for now, is to use a video camera to record the process of hardware testing (as 'live' video) - and do a desktop capture at the same time. The video camera produces a 29.97 (30) FPS MPEG-2 .AVI video; and I want to get the desktop capture as an image sequence of PNGs at the same frame rate as the video. The idea, then, would be: if the frame rate of the two videos is the same; then I could simply

  • align the time of start of the desktop capture, with the matching point in the 'live' video
  • Set up a picture-in-picture, where a scaled down version of the desktop capture is put - as overlay - on top of the 'live' video
    • (where a portion of the screen on the 'live' video, serves as a visual sync source with the 'desktop capture' overlay)
  • Export a 'final' combined video, compressed appropriately for the Internet

In principle, I guess one could use a command line tool like ffmpeg for this process; however I would prefer to use a GUI for finding the alignment start point for the two videos.

Eventually, what I also want to achieve, is to preserve maximum quality when exporting the 'final' video: the 'live' video is already compressed when out of the camera, which means additional degradation when it passes through the Theora .ogv codec - which is why I'd like to keep the original videos, and use something like a command line to generate a 'final' video anew, if a different compression/resolution is required. This is also why I like to have the 'desktop capture' video as a PNG sequence (although I guess any uncompressed format would do): I take measures to 'adjust' the desktop, so there aren't many gradients, and lossless encoding (i.e. PNG) would be appropriate.
 
 

Desktop capture options

Well, there are many troubles in this process under Ubuntu Lucid, which I currently use (and you can read about some of my ordeals in 10.04: Video overlay/composite editing with Theora ogv - Ubuntu Forums). However, one of the crucial problems is the assumption, that the frame rate of the two incoming videos is equal - in reality, usually the desktop capture is of a lower framerate; and even worse, very often frames are out of sync.

This, then, requires the hassle of sitting in front of a video editor, and manually cutting and editing less-than-a-second clips on frame level - requiring hours of work for what will be in the end a 5 minute video. On the other hand, if the two videos ('live' and 'capture') did have the same framerate and sync: in principle, you wouldn't need more than a couple of minutes for finding the start sync point in a video editor - and the rest of the 'merged' video processing could be handled by a single command line. Which is why, in this post, I would like to focus on the desktop capture part.

As far as I can see, there are only few viable (as opposed to 5 Ways to Screencast Your Linux Desktop) alternatives for desktop capture in Linux / Ubuntu (note, I typically use a laptop as target for desktop capturing):

  1. Have your target PC (laptop) clone the desktop on its VGA output; use a VGA-to-composite or VGA-to-S-video hardware to obtain a video signal from VGA; use video capture card on a different PC to grab video
  2. Use recordMyDesktop on the target PC
  3. Set up a VNC server (vino on Ubuntu; or vncserver) on the target PC to be captured; use VNC capture software (such as vncrec) on a different PC to grab/record the VNC stream (which can, subsequently, be converted to video).
  4. Use ffmpeg with x11grab option
  5. *(use some tool on the target PC, that would do a DMA transfer of a desktop image frame directly - from the graphics card frame buffer memory, to the network adapter memory)

Please note that the usefulness of the above approaches are limited by my context of use: the target PC that I want to capture, typically runs software (utilizing the tested hardware) that moves around massive ammounts of data; best you could say about describing such a system is "barely stable" :) I'd guess this is similar to problems gamers face, when wanting to obtain a video capture of a demanding game. And as soon as I start using something like recordMyDesktop, which also uses quite a bit of resources and wants to capture on the local hard disk - I immediately get severe kernel crashes (often with no vmcore generated).

So, in my context, I typically do assume involvement of a second computer - to run the capture and recording of the 'target' PC desktop. Other than that, the pros and cons I can see so far with the above options, are included below.

(Desktop preparation)

For all of the methods discussed below, I tend to "prepare" the desktop beforehand:

  • Remove desktop backgrounds and icons
  • Set the resolution down to 800x600 via System/Preferences/Monitors (gnome-desktop-properties)
  • Change color depth down to 16 bpp (using xdpyinfo | grep "of root" to check)

... in order to minimize the load on desktop capture software. Note that changing color depth on Ubuntu requires changes to xorg.conf; however, "No xorg.conf (is) found in /etc/X11 (Ubuntu 10.04)" - so you may need to run sudo Xorg -configure first.

In order to keep graphics resource use low, also I usually had compiz disabled - or rather, I'd have 'System/Preferences/Appearance/Visual Effects' set to "None". However, after I tried enabling compiz by setting 'Visual Effects' to "Normal" (which doesn't get saved), I can notice windows on the LCD screen are redrawn much faster; so I keep it like this, also for desktop capture. I find this a bit strange: how could more effects cause a faster screen refresh? It doesn't look like it's due to a proprietary driver (the card is "Intel Corporation N10 Family Integrated Graphics Controller", and no proprietary driver option is given by Ubuntu upon switch to compiz) - although, it could be that all the blurring and effects just cheat my eyes :) ).

Cloning VGA

Well, this is the most expencive option (as it requires additional purchase of not just one, but two pieces of hardware: VGA converter, and video capture card); and applicable mostly to laptops (which have both a screen + additional VGA output - for desktops one may also have to invest in an additional graphics card, or a VGA cloning hardware).

However, it is also the only option that requires no additional software of the target PC whatsoever (and thus uses 0% processing power of the target CPU) - AND also the only one that will give a video with a true, unjittered framerate of 30 fps (as it is performed by separate hardware - although, with the assumption that clock domains misalignment, present between individual hardware pieces, is negligible).

Actually, as I already own something like a capture card, I have already invested in a VGA converter - in expectation that it will eventually allow me to produce final "merged" videos with only 5 mins of looking for alignment point, and a single command line; but I am yet to see whether this process will work as intended. I'm also wandering how possible it will be to capture desktop as uncompressed video @ 800x600, 30 fps.

recordMyDesktop

Well, if you run recordMyDesktop without any arguments - it starts first with capturing (what looks like) raw image data, in a folder like /tmp/rMD-session-7247; and after you press Ctrl-C to interrupt it, it will encode this raw image data into an .ogv. Obviously, grabbing large image data on the same hard disk as my test software (which also moves large ammounts of data), is usually a cause for an instacrash :)

Hence, what I tried doing is to setup Samba to share a drive on the network; then on the target PC, I'd connect to this drive - and instruct recordMyDesktop to use this network drive (via gvfs) as its temporary files location:

recordmydesktop --workdir /home/user/.gvfs/test\ on\ 192.168.1.100/capture/ --no-sound --quick-subsampling --fps 30 --overwrite -o capture.ogv 

Note that, while this command will use the network location for temporary files (and thus makes it possible for recordMyDesktop to run in parallel with my software) - as soon as you hit Ctrl-C, it will start encoding and saving capture.ogv directly on the local hard drive of the target (though, at that point, I don't really care :) )

First of my nags with recordMyDesktop is that you cannot instruct it to keep the temporary files, and avoid encoding them, on end: you can use Ctrl+Alt+p for pause - or you can hit Ctrl-C quickly after the first one, to cause it to crash; which will then leave the temporary files (if you don't hit Ctrl-C quickly enough the second time, the program will "Cleanning up cache..."). You can then run, say:

recordmydesktop --rescue /home/user/.gvfs/test\ on\ 192.168.1.100/capture/rMD-session-7247/

... in order to convert the raw temporary data. However, more often than not, recordMyDesktop will itself segfault in the midst of performing this "rescue". Although, the reason why I want to keep the temp files, is to have the uncompressed source for the picture-in-picture montage. Note that the "--on-the-fly-encoding" will avoid using temp files altogether - at the expence of using more CPU processing power (which, for me, again is cause for crashes.)

Then, there is the framerate - obviously, you can set requested framerate using the '--fps N' option; however, that is no guarantee that you will actually obtain that framerate; for instance, I'd get:

recordmydesktop --fps 25
...
Saved 2983 frames in a total of 6023 requests
...

... for a capture with my test software running; which means that the actually achieved rate is more like 25*2983/6032 = 12.3632 fps!

Obviously, frames are dropped - and mostly that shows as video playback is too fast. However, if I lower the requested fps to 12 - then according to saved/total reports, I achieve something like 11 fps; and in this case, video playback doesn't look 'sped up'. And I still haven't tried aligning such a capture with a live video - so I have no idea if those frames that actually have been saved, also have an accurate timestamp.

VNC capture

The VNC capture, for me, consists of running a VNC server on the 'target' PC, and running vncrec (twibright edition) on the 'recorder' PC. As VNC server, I use vino, which is "System/Preferences/Remote Desktop (Preferences)". And apparently, even if vino configuration may not be the easiest thing to manage, vino as a server seems not too taxing to the 'target' PC; as I haven't experienced crashes when it runs in parallel with my test software.

On the other hand, when vncrec is capturing on the 'recorder' PC, it also raises a window showing you the 'target' desktop as it is seen in 'realtime'; when there are large updates (i.e. whole windows moving) on the 'target' - one can, quite visibly, see problems with the update/refresh rate on the 'recorder'. But, for only small updates (i.e. just a cursor moving on a static background), things seem OK.

This makes me wonder about one of my primary questions with this post - what is it, that sets the framerate in a VNC connection?

I haven't found a clear answer to this, but from bits and pieces of info (see refs below), I gather that:

  • The VNC server simply sends changes (screen changes + clicks etc) as fast as it can, when it receives them ; limited by the max network bandwidth that is available to the server
  • The VNC client receives those change events delayed and jittered by the network connection, and attempts to reconstruct the desktop "video" stream, again as fast as it can

... which means, one cannot state anything in terms of a stable, periodic frame rate (as in video).

As far as vncrec as a client goes, the end videos I get usually are declared as 10 fps, although frames can be rather displaced/jittered (which then requires the cutting in video editors). Note that the vncrec-twibright/README states: "The sample rate of the movie is 10 by default or overriden by VNCREC_MOVIE_FRAMERATE environment variable, or 10 if not specified."; however, the manpage also states "VNCREC_MOVIE_FRAMERATE - Specifies frame rate of the output movie. Has an effect only in -movie mode. Defaults to 10. Try 24 when your transcoder vomits from 10.". And if one looks into "vncrec/sockets.c" source, one can see:

void print_movie_frames_up_to_time(struct timeval tv)
{
  static double framerate;
  ....
  memcpy(out, bufoutptr, buffered);
  if (appData.record)
    {
      writeLogHeader (); /* Writes the timestamp */
      fwrite (bufoutptr, 1, buffered, vncLog);
    }

... which shows that some timestamps are written - but whether those timestamps originate from the "original" 'target' PC, or the 'recorder' one, I cannot tell.
EDIT: thanks to the answer by @kanaka, I checked through vncrec/sockets.c again, and can see that it is the writeLogHeader function itself calling gettimeofday; so the timestamps it writes are local - that is, they originate from the 'recorder' PC (and hence, these timestamps do not accurately describe when the frames originated on the 'target' PC).

In any case, it still seems to me, that the server sends - and vncrec as client receives - whenever; and it is only in the process of encoding a video file from the raw capture afterwards, that some form of a frame rate is set/interpolated.

I'd also like to state that on my 'target' laptop, the wired network connection is broken; so the wireless is my only option to get access to the router and the local network - at far lower speed than the 100MB/s that the router could handle from wired connections. However, if the jitter in captured frames is caused by wrong timestamps due to load on the 'target' PC, I don't think good network bandwidth will help too much.

Finally, as far as VNC goes, there could be other alternatives to try - such as VNCast server (promising, but requires some time to build from source, and is in "early experimental version"); or MultiVNC (although, it just seems like a client/viewer, without options for recording).

ffmpeg with x11grab

Haven't played with this much, but, I've tried it in connection with netcat; this:

# 'target'
ffmpeg -f x11grab -b 8000k -r 30 -s 800x600 -i :0.0 -f rawvideo - | nc 192.168.1.100 5678
# 'recorder'
nc -l 0.0.0.0 5678 > raw.video  #

... does capture a file, but ffplay cannot read the captured file properly; while:

# 'target'
ffmpeg -f x11grab -b 500k -r 30 -s 800x600 -i :0.0 -f yuv4mpegpipe -pix_fmt yuv444p - | nc 192.168.1.100 5678
# 'recorder'
nc -l 0.0.0.0 5678 | ffmpeg -i - /path/to/samplimg%03d.png

does produce .png images - but with compression artifacts (result of the compression involved with yuv4mpegpipe, I guess).

Thus, I'm not liking ffmpeg+x11grab too much currently - but maybe I simply don't know how to set it up for my needs.

*( graphics card -> DMA -> network )

I am, admittedly, not sure something like this exists - in fact, I would wager it doesn't :) And I'm no expert here, but I speculate:

if DMA memory transfer can be initiated from the graphics card (or its buffer that keeps the current desktop bitmap) as source, and the network adapter as destination - then in principle, it should be possible to obtain an uncompressed desktop capture with a correct (and decent) framerate. The point in using DMA transfer would be, of course, to relieve the processor from the task of copying the desktop image to the network interface (and thus, reduce the influence the capturing software can have on the processes running on the 'target' PC - especially those dealing with RAM or hard-disk).

A suggestion like this, of course, assumes that: there are massive ammounts of network bandwidth (for 800x600, 30 fps at least 800*600*3*30 = 43200000 bps = 42 MiB/s, which should be OK for local 100 MB/s networks); plenty of hard disk on the other PC that does the 'recording' - and finally, software that can afterwards read that raw data, and generate image sequences or videos based on it :)

The bandwidth and hard disk demands I could live with - as long as there is guarantee both for a stable framerate and uncompressed data; which is why I'd love to hear if something like this already exists.

-- -- -- -- -- 

Well, I guess that was it - as brief as I could put it :) Any suggestions for tools - or process(es), that can result with a desktop capture

  • in uncompressed format (ultimately convertible to uncompressed/lossless PNG image sequence), and
  • with a "correctly timecoded", stable framerate

..., that will ultimately lend itself to 'easy', single command-line processing for generating 'picture-in-picture' overlay videos - will be greatly appreciated!

Thanks in advance for any comments,
Cheers!


References

  1. Experiences Producing a Screencast on Linux for CryptoTE - idlebox.net
  2. The VideoLAN Forums • View topic - VNC Client input support (like screen://)
  3. VNCServer throttles user inpt for slow client - Kyprianou, Mark - com.realvnc.vnc-list - MarkMail
  4. Linux FAQ - X Windows: How do I Display and Control a Remote Desktop using VNC
  5. How much bandwidth does VNC require? RealVNC - Frequently asked questions
  6. x11vnc: a VNC server for real X displays
  7. HowtoRecordVNC (an X11 session) - Debian Wiki
  8. Alternative To gtk-RecordMyDesktop in Ubuntu
  9. (Ffmpeg-user) How do I use pipes in ffmpeg
  10. (ffmpeg-devel) (PATCH) Fix segfault in x11grab when drawing Cursor on Xservers that don't support the XFixes extension

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

囚我心虐我身 2024-10-12 06:16:07

这么长的问题你应该得到一个徽章。 ;-)

为了回答您的主要问题,VNC 使用 RFB 协议,该协议是远程帧缓冲区协议(因此是缩写)而不是流视频协议。 VNC 客户端向服务器发送 FrameBufferUpdateRequest 消息,其中包含客户端感兴趣的视口区域和增量标志。如果未设置增量标志,则服务器将使用包含所请求区域的内容的 FrameBufferUpdate 消息进行响应。如果设置了增量标志,则服务器可以使用 FrameBufferUpdate 消息进行响应,该消息包含自上次向客户端发送该区域以来所请求的区域中已更改的任何部分。

请求和更新如何交互的定义没有明确定义。如果没有任何变化,服务器不一定会通过更新来响应每个请求。如果服务器有来自客户端的多个请求排队,则还允许发送单个更新作为响应。此外,客户端确实需要能够响应来自服务器的异步更新消息(而不是响应请求),否则客户端将失去同步(因为 RFB 不是帧协议)。

通常,客户端只是简单地实现为以周期性间隔发送整个帧缓冲区视口的增量更新请求,并在服务器更新消息到达时处理它们(即,不尝试将请求和更新绑定在一起)。

这里是 FrameBufferUpdateRequest 消息的描述。

You should get a badge for such a long well though out question. ;-)

In answer to your primary question, VNC uses the RFB protocol which is a remote frame buffer protocol (thus the acronym) not a streaming video protocol. The VNC client sends a FrameBufferUpdateRequest message to the server which contains a viewport region that the client is interested in and an incremental flag. If the incremental flag is not set then the server will respond with a FrameBufferUpdate message that contains the content of the region requested. If the incremental flag is set then the server may respond with a FrameBufferUpdate message that contains whatever parts of the region requested that have changed since the last time the client was sent that region.

The definition of how requests and updates interact is not crisply defined. The server won't necessarily respond to every request with an update if nothing has changed. If the server has multiple requests queued from the client it is also allowed to send a single update in response. In addition, the client really needs to be able to respond to an asynchronous update message from the server (not in response to a request) otherwise the client will fall out of sync (because RFB is not a framed protocol).

Often clients are simply implemented to send incremental update requests for the entire frame buffer viewport at a periodic interval and handle any server update messages as they arrive (i.e. no attempt is made to tie requests and updates together).

Here is a description of FrameBufferUpdateRequest messages.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文