單一視窗畫面擷取

前陣子有一名客戶希望能將大尺寸的螢幕平放,然後在兩個長邊的地方各坐兩個人,很像是一張桌子坐了四個人,兩兩相望。
不過由於客戶的程式只有單一視窗,也不能修改這隻程式讓它直接輸出就可以分四格畫面,且電腦主機只有一個 HDMI 輸出。

仔細想想,應該是要再另外寫一隻程式,不斷的去捕捉客戶的程式畫面,並複製成四宮格 (上面的那兩格要 180 度旋轉),蓋在整個畫面的上方。

一開始想到的是用 ffmpeg 針對客戶的程式去錄影並做成串流伺服器,我只要寫個程式去播放這個串流就好了。

不過可惜的是,Windows 似乎沒有 ffserver?所以還要弄成 ffmpeg + vlc 之類的… 有點複雜。我後來沒有採用這種方式,但,ffmpeg 能針對單一的視窗去錄影嗎?可以的,用 gdigrab

$ ffmpeg -re -f gdigrab -framerate 20 -draw_mouse 0 -i title=window_name \ 
    -vcodec libx264 -preset ultrafast \
    -tune zerolatency -f mpegts udp://127.0.0.1:1234

-i title=window_namewindow_name 是你要錄影的視窗 title。-i desktop 則可以抓取整個桌面。gdigrab 的參數可以
參考這裡


然後再搭配 vlc 作串流播出,這裡有影片教學。我測試的時候,效果不太好,會有點 lag,可能參數那邊要再調整。


後來我想到用 Qt 來試試看,找了一下資料,發現是有可能針對特定視窗去錄製畫面的。關鍵在 QScreen::grabWindow(),大概的用法是:

#include <Windows.h>

Qscreen *screen = QGuiApplication::primaryScreen();
QPixmap picOrig = screen-&gt;grabWindow((WId) FindWindow(NULL, L"視窗名稱"));

// 旋轉
QTransform trans;
trans = trans.rotate(180);
QPixmap picTrans = picOrig.transformed(trans);

// 現在 picOrig 是正常的畫面,picTrans 是旋轉過的畫面

FindWindow() 是 Windows 的 API,所以要 #include <Windows.h>
再來就只要不斷的去抓取這個畫面就行了。


後來我發現是我誤會客戶的意思,所以… 就當作是一次寶貴的經驗吧。😦