2014年11月25日 星期二

網路媒體播放器 VLC :循序漸進的命令列教學

VLC 影片/音樂播放器超級強大。 本文由簡至繁, 逐步進階, 教你如何用命令列操作 vlc, 用它來播放/錄製/廣播各種來源的影音: 包含檔案、 網路攝影機、 桌面活動。 當你學會各種基本語法, 再拿它來排列組合時, 就可以自由實現廣播、 遠端監視錄影、 錄製電腦操作教學影片、 ... 等等效果。 注意! 從 「六、網路放送」 那一節 (含) 之後, 許多指令都有洩漏隱私的高度風險!

一、 影片檔的基本概念及術語

影片格式 其實貴哥對影片檔和影音相關技術也超級不熟的。 不過沒關係, 只需學要一點點基本概念, 以下的指令就會變得容易理解許多。 這一節先來介紹一下基本語彙。 一個影片檔裡面, 其實還包含畫面、 聲音、 字幕 (subtitle)、 文字資訊 (創作者/日期/授權/... 通稱為 metadata) 等等四個部分。 在談論 「影片格式轉換」 的時候, 我們所關心的, 有可能是外面這個大檔 (稱為 container) 的打包/包裝方式, 也有可能是指裡面的畫面部分 (稱為 video stream) and/or 聲音部分 (稱為 audio stream) 的編碼方式 (採用哪一種 encoding)。

如果只是 「拆開外包裝取出獨立畫面/取出獨立聲音」 這個動作稱為 demuxing; 至於重新打包, 當然就叫做 remuxing。 又例如要把字幕加入影片檔裡面, 也只需要拆開 container 再重新打包。 (soft-subtitling)

如果想要降低解析度/畫質 (以便減少檔案大小) 或是製造聲音特效等等, 就需要對裡面的 video stream 或是 audio stream 重新編碼。 在 vlc 指令裡面, 有一個 transcode 模組專門在負責這件複雜的事。

二、 播放影片基本動作

以下我用 ClipConverter 線上轉檔服務把 music of the night 抓下來存成 music-of-the-night.mp4 做實驗。

  1. vlc 最簡單的用法, 就是播放某個影片檔: vlc music-of-the-night.mp4
  2. 設定檔在 ~/.config/vlc/vlcrc 。 比方說, 如果希望它播完之後不斷地重播, 可以在設定檔裡面找到 loop=...repeat=... 那一句, 把註解拿掉 (刪掉 # 號), 並且把 0 改成 1。 (loop 是全部重播; repeat 是重播一首/一部影片。)
  3. 其中有許多設定, 也可以用命令列選項達成心願。 例如: vlc --loop music-of-the-night.mp4vlc --repeat music-of-the-night.mp4 。 更多選項請見: vlc -h | less 完整的選項清單請見: vlc -H | less
  4. 播完就直接結束, 不要留在 vlc 的圖形介面: vlc --play-and-exit music-of-the-night.mp4 或是這樣也可達到相同效果: vlc music-of-the-night.mp4 vlc://quit
  5. 如果你的電腦有接 webcam, 可以這樣看: vlc v4l2:///dev/video0

往下做之前, 請先編輯 ~/.config/vlc/vlcrc 找到 ffmpeg-threads 這一句, 把它改成 ffmpeg-threads=1。 (如果前面有 # 也要把它拿掉。) 我忘記是在試哪一個功能的時候 (應該是 「四、 轉檔時指定編碼格式」) 遇到 "width height bit depth chroma idc changing with threads is not implemented" 之類的錯誤訊息。 搜尋到 1 2 3 等等文章/問答, 再自行找到設定檔如上修改就 OK 了。

三、 「重新打包」 學習 vlc 基本命令格式

再來我們用不同的 container 格式把既有的影片檔重新打包, 另存新檔 (裡面的 video stream 跟 audio stream 的編碼方式維持不變): vlc music-of-the-night.mp4 :sout='#std{access=file, mux=avi, dst="music-of-the-night.avi"}' vlc://quit

請修改上句, 自己填入適當的格式 (mux=...) 及目的地檔名 (dst=...)。 根據維基百科的 container 格式比較表, 如果沒有把握時, 可優先採用 avi、 mp4、 mkv 這幾個格式, 因為這幾個 container 格式能夠吃下最多種不同的 video stream 與 audio stream 格式。 至於 vlc 支援哪些 mux 格式? 詳見 這裡

這一指令也讓我們學習 vlc 的基本命令格式。 當我們要叫 vlc 把輸出存檔時, 就採用 :sout='#std{access=file,...}' 這個固定的指令。 這裡的 :sout='...' 也可寫成 --sout '...' (注意要有空格!) 而 std 其實是 standard 的簡寫。

你會注意到 vlc 視窗跳出來一下子, 轉完檔之後馬上又不見了。 既然我們只是單純轉檔, 沒有要看內容, 其實可以改用 vlc --intf dummy ... 或是更簡單的 cvlc ... 指令, 很 man 很帥氣地完全省略 vlc 視窗。

順便一提, 如果只是要轉檔而沒有要播放, 在 linux 底下還有一個更輕量級、 也很 man 的 ffmpeg 指令可用。 詳見 man ffmpeg ^_*

如果想要一邊轉檔一邊播放到螢幕上觀賞, 則可以把 :sout='... 那一段改成這樣: :sout='#duplicate{dst=display, dst=std{access=file,...}}'

四、 轉檔時指定編碼格式

如果是處理既有的影片檔, 其實並不太需要指定 video stream 跟 audio stream 的編碼格式。 但因為後面我們還要錄影螢幕 (例如軟體操作教學) 或是從攝影機/網路相機擷取影像/錄影, 而這些裝置提供的可能是更低階、 未加工或只加工一半的原始資料 (別問我 細節, 我也不懂) 所以此時就一定要指定編碼格式。

不過我們還是先以讀者已經很熟悉的 (?!) 轉檔為例: cvlc music-of-the-night.mp4 :sout='#transcode{vcodec=theo,acodec=vorb} : std{access=file, mux=ogg, dst="music-of-the-night.ogv"' vlc://quit 這裡的重點是: 那一小段加在 std{...} 之前的 transcode{...} 轉編碼子句。 (兩個子句之間以冒號分隔) 我們採用完全自由開放的 ogg theora 影像格式與 ogg vorbis 聲音格式 來編碼; 輸出時也順便把外包裝改成完全自由開放的 ogg container 格式。 更多參數請參考 這一頁的範例。 你會注意到: 與 「重新打包」 相較, 「轉編碼格式」 的速度慢了許多 -- 它很操 CPU。

其他更多可用的編碼格式請參考 vlc 的 wiki

到這裡, 再加上一點點 shell script 的迴圈知識, 你已經有能力 批次轉檔 -- 一口氣把很多影片檔轉成相同的格式。 命令列無敵!

注意: 本文當中許多轉影音編碼相關的指令都盡量採用最簡單的版本; 很多其他參數 (取樣頻率、 畫質、 音質、 ... 等等) 都是能省則省, 所以產生出來的新檔案, 影音品質可能不甚理想。 請上網搜尋其他教學文更詳細的推薦參數。

五、 從影片當中擷取出聲音檔

想從從影片當中擷取出聲音檔, 重點就是在 transcode 的時候, 指定 vcodec=none 丟棄影像資料。 例如想把擷取出來的聲音檔存成 ogg vorbis 開放格式: cvlc -v music-of-the-night.mp4 :sout='#transcode{vcodec=none, acodec=vorb} :std{access=file, mux=ogg, dst="music-of-the-night.ogg"}' vlc://quit 除了 vlc 可以播放 .ogg 檔之外, 也可安裝比較輕薄短小的 vorbis-tools 套件, 用 ogg123 指令播放 .ogg 聲音檔。 又例如想把擷取出來的聲音檔存成常見的 mp3 格式: cvlc -v music-of-the-night.mp4 :sout='#transcode{vcodec=none, acodec=mp3} :std{access=file, mux=mp3, dst="music-of-the-night.mp3"}' vlc://quit

這一部 5 分多的影片檔, 從當中擷取聲音檔, 轉成 ogg 耗時 86 秒; 轉成 mp3 耗時 10 秒。 如此大的差距, 跟原始檔案的格式不知道有沒有關係。

跟影片轉檔一樣, 學會用命令列擷取聲音部分之後, 再加一點 shell script, 很容易就可以批次擷取很多影片的聲音軌。

六、 網路放送

要把 vlc 當做網路影音廣播站 (串流伺服器 streaming server), 有幾種不同的通訊協定可以選擇。 我也不知道每一種的優缺點 :-( (只有搜尋到一篇 比較 rtp 與 udp 的問答) 只能把實驗成功的指令列出來供大家參考。 這一節的練習, 採用現成的影音檔當做來源, 這樣可以省略 transcode 複雜的子句, 比較容易專注於網路廣播那部分的語法。 注意: 本節完全沒有考慮資料上網前預先加密保護, 所以很多指令可能會洩漏你的隱私! 以下假設廣播站的 IP 是 192.168.135.246 。

rtp/rtsp ( 簡要中文解說) 是專為串流媒體所設計的即時通訊協定。 在伺服器端下: vlc music-of-the-night.mp4 :sout='#rtp{sdp=rtsp://:8554/motn}' 然後在客戶端下: vlc rtsp://192.168.135.246:8554/motn 即可播放。 其中 8554 可以是你自己任選的 port number; motn 可以是你自己任選的頻道名稱。

如果需要跨越防火牆, 或許可改採 (不太可能被封鎖的) http。 在伺服器端下: vlc music-of-the-night.mp4 :sout='#std{access=http, mux=ts, dst=:8080}' 然後在客戶端下: vlc http://192.168.135.246:8080 即可播放。 其中 8080 可以是你自己任選的 port number;

不論是 rtp/rtsp 或是 http, 如果先啟動客戶端, 會出現錯誤訊息; 等伺服器啟動之後, 回到客戶端按一下 「播放」 鍵即可。

vlc 還支援 multicast 廣播, 不知道是不是在區網裡可以超快速廣播。 在伺服器端下: vlc music-of-the-night.mp4 :sout='#rtp{mux=ts, dst=239.1.1.17, port=5004"}' 然後在客戶端下: vlc rtp://@239.1.1.17:5004 即可播放。 在區網裡採用 multicast 時, 網址一律以 239 開頭; port number 則一樣可以任選 (上例中的 5004)。 (略讀一下 維基百科, multicast 好像也可以跨越區網; 不過我沒空學了。) 好處是: 伺服器停掉的時候, 客戶端畫面定格; 伺服器重新上線的時候, 客戶端自動開始播放。

一個 (適用於以上三種協定的) 有趣的網路播放選項是: 在客戶端用 --network-caching 指定 cache 的時間, 刻意延長 lag。 例如在一部客戶端電腦下: vlc --network-caching=1000 rtsp://192.168.135.246:8554/motn 在另一部客戶端電腦下: vlc --network-caching=5000 rtsp://192.168.135.246:8554/motn 那麼第一部的 cache 只有一秒, 第二部則有五秒, 所以第二部會晚四秒鐘播放。 覺得這可以拿來玩輪唱...

如果想要一邊網路播放一邊在地存檔, 在伺服器那邊, 可以用先前學過的 duplicate 語法: :sout '#duplicate{dst=rtp{...}, dst=std{access=file,...}}'

好了, 現在你再去看官方文件關於廣播的那一部分: Chapter 4. Examples for advanced use of VLC's stream output (transcoding, multiple streaming, etc...) 應該就會比貴哥當初自學時要容易多了。

更多與廣播相關的教學文:

  1. Setting up a multicast lab using VLC 2.0.5

七、 監視/錄影

現在你已經會從網路攝影機 (webcam) 取得資料, 再加上存檔或網路傳輸的功能, 就可以把自己的影像傳給別人了。 但是 vlc 可能是為了要儲存足夠的 buffer, 會 lag 好幾秒, 所以不太適合用來打網路電話, 只適合用來監看。 因為沒有人願意被我監看 (無誤), 所以只好監看電視做實驗。

首先幫位於客廳的筆電準備好一個舒適的位置與角度, 讓鏡頭面對電視。 在筆電上面: cvlc v4l2:// :v4l-vdev="/dev/video0" :input-slave=alsa:// :sout='#transcode{vcodec=mjpg, acodec=vorbis} : std{access=http, mux=ogg, dst=:8080}' 然後在書房裡用桌機連線至筆電 (假設筆電的 IP 是 192.168.135.246) : vlc http://192.168.135.246:8080 於是沒有電視卡的我, 也可以在電腦上看電視了! (北極熊: 「你這樣浪費電我的家會融化掉耶!」)

[2016/8/28] 「在老舊電腦上跑 vlc streaming 服務」 有更多監視錄影效能調校技巧。

也可以改用 rtp/rtsp 重做一次。 但 rtp/rtsp 不支援 ogg 格式, 所以改用 mp4 的 ts 格式。 在筆電上面: cvlc v4l2:// :v4l-vdev="/dev/video0" :input-slave=alsa:// :sout='#transcode{vcodec=mp4v, vb=4096, acodec=mpga} : rtp{sdp=rtsp://:8554/living_room_tv}' 然後在書房裡, 用桌機連線至筆電: vlc rtsp://192.168.135.246:8554/living_room_tv

改用 rtp/multicast 再做一次。 在筆電上面: cvlc v4l2:// :v4l-vdev="/dev/video0" :input-slave=alsa:// :sout='#transcode{vcodec=mp4v, vb=4096, acodec=mpga} : rtp{mux=ts, dst=239.1.1.17, port=5004"}' 然後在書房裡, 用桌機連線至筆電: vlc rtp://@239.1.1.17:5004 播放檔案的時候用 rtp/multicast 還 OK; 但現在加上 transcode, 似乎是因為我的筆電運算不夠快、 rtp/multicast 比較低階, 一直掉封包又沒有檢查, 所以效果不太好。

原先我在筆電上放送影片時, 不懂得用 cvlc 關掉本地播放, 結果 vlc 一邊把麥克風接到的聲音播放出來, 一邊又繼續用麥克風把幾秒前的聲音一併錄回去, 造成迴音繞樑... 有一種 「被選舉宣傳車轟炸」 的感覺。 (想起小時候拿著兩面鏡子互照...)

當然, 如果把輸出子句改成存檔, 那麼 vlc 加上 webcam, 就變成了錄影工具: cvlc v4l2:// :v4l-vdev="/dev/video0" :input-slave=alsa:// :sout='#transcode{vcodec=theo, acodec=vorb} : std{access=file, mux=ogg, dst="x.ogg"}'

本節參考連結:

  1. How to live stream video from webcam on Linux
  2. vlc live streaming from v4l
  3. Stream from an acquisition card or a webcam
  4. Streaming v4l-captured video over the network

八、 錄製或傳送桌面活動

可以這樣子錄下桌面活動: cvlc screen:// :input-slave=alsa:// :screen-fps=10 :screen-follow-mouse :sout='#transcode{acodec=vorb, vcodec=theo, vb=1024, scale=0.8} :std{access=file, mux=ogg, dst="screencast01.ogv"}' 例如要製做軟體教學影片之類的時候很好用。 這裡的 :screen-fps=10 是指每秒取樣十張畫面快照。 詳見 Encoding (Ogg Theora) with VLC

如果把最後一段改成 :std{access=http, mux=ts, dst=:8080} 那就變成網路廣播教學。 不過會有好幾秒鐘的 lag。 如果單純只是要廣播教學, 推薦: 「遠端桌面連線軟體 VNC 也可以當成電子白板或廣播教學軟體來用」

如果 ogv/ogg 格式壓縮速度太慢, 可以考慮改採 mp4 格式: cvlc screen:// :input-slave=alsa:// :screen-fps=10 :screen-follow-mouse :sout='#transcode{acodec=mpga, vcodec=h264, vb=1024, scale=0.8, venc=x264{scenecut=100, bframes=0, keyint=10}} :std{access=http, mux=ts, dst=:8080}'

不知為什麼, 採用 mp4v 格式來錄製螢幕畫面時, 畫面不會更新, 而且也不能用 scale (會出現 aspect ratio error 的錯誤)。

本節參考連結:

  1. Capture a Screencast Using VLC
  2. Stream desktop using VLC

九、 隱私保護以及其他考量?

本文完全沒有考慮資訊安全。 特別是 「網路放送」、 「監視/錄影」、 「錄製或傳送桌面活動」 這幾節在做的事, 如果沒有加密就直接在網路上傳送, 可能會有侵權或洩漏隱私的風險! 不過這篇文章已經寫了好幾個禮拜, 我沒力氣了。 加密保護隱私的問題, 以後再另文處理吧。

提到侵權的問題, 順便推: Creative Commons Video Sharing Sites and Social Media Tools。 這一頁蒐集了很多創用 CC 授權影片網站的連結。

為什麼我會想學 vlc 的命令列? 未來 raspberry pi 或 banana pi 或平價平板之類的硬體, 應該會創造出很多低價位的影音應用情境。 (例如 telepresence) 現在學會用命令列的方式操作 vlc, 將來就可以在這些小電腦上面寫 shell script 做很多有趣的事。 總有一天, 會出現一些神奇的應用, 讓更多人看懂這一篇 「長線投資的電腦學習策略」, 並且終於領悟到: 自由硬體 + 自由軟體 + scripting 的各種高靈活度排列組合, 是滑鼠選單學習模式難以追得上的。

4 則留言:

  1. 標題錯字,VNC→VLC...

    回覆刪除
  2. 請問最後的 「當然, 如果把輸出子句改成存檔, 那麼 vlc 加上 webcam, 就變成了錄影工具: cvlc v4l2:// :v4l-vdev="/dev/video0" :input-slave=alsa:// :sout='#transcode{vcodec=theo, acodec=vorb} : std{access=file, mux=ogg, dst="x.ogg"}'」
    這是哪個部分 我有卡回音這個問題
    一直都沒辦法解決
    跪求 !!! 謝謝

    回覆刪除
    回覆
    1. 這是在客廳的筆電上面下指令,存在筆電裡。 這個例子沒用到第二部電腦。 若還是遇到問題,請詳細描述你的狀況、在哪裡下哪個指令, 這樣我才有辦法試著回答哦。

      刪除