正文開始
前面聲音與影像的基本原理都學習完後,咱們接下來要來實作一些東西。
在筆者的30-09之別人要如何聽到我的聲音呢 ?有提到三種影音的傳遞方式,分別為:
- 將聲音檔案直接丟給對方 ( 方法 1 )
- 將聲音檔案以串流的方式傳送給對方 ( 方法 2 )
- 像直播或網路電話一樣即時的將聲音傳送給對方 ( 方法 3 )
接下來我們將來實作方法 2 的選項,而這東西事實上就是點播網站的應用,像 KKTV、楓林網就是這種類型的應用,本篇文章將會說明:
如何建立的像 KKTV 一樣的點播功能呢 (可以動就好版) ?
先說好,如果真的要建立像 KKTV 一樣的可營運的應用,還需要做不少架構的調整,這裡就是只是學習如何做出可以動的點播網站,也就是可以看片 (不是全部下載完才可以看)。
本篇將分為以下幾個章節:
- 點播架構原理。
- 實作 - 建立 Media Server。
- 實作 - 網頁用戶端取得串流影像。
架構原理
基本上點播的架構,最基本(不管流量或 CDN 這些鬼)的樣貌會如下:
然後基本上可以選擇的協議有RTMP
、HLS
、HTTP-FLV
、MPEG-DASH
。
那這裡問個問題 ?
我要選擇那個協議呢 ?
基本上我覺得是要看你的用戶端的裝置取向,基本上以現在的狀態選擇 HLS 與 MPEG-DASH 在點播類的應用,應該是最安穩的,最主要我覺得有以下三個原因:
- 這兩個都是使用 HTTP 來傳輸,不太會發生有的用戶可以看有的不行。
- 大部份的平台都可以找到方法支援。
- 這兩種都有支援依劇網路狀況,來自動調整畫質的功能,這在看影片時尤其有用。
這兩個協議可以去參考筆者的以下兩篇文章。
30-17之 MPEG-DASH 傳輸協議 30-15之 HLS 傳輸協議
接下來咱們就先以 HLS 為主,來開始來進行實作 ( Dash 的建立實際上也差不多 )。
實作 - 建立 Media Server
首先第一部,我們要先建立一個 Media Server,它的主要功能有以下兩個:
- 可以將影片檔轉換成 HLS 使用的 .m3u8。(不一定要在 Media Server 中處理,這裡只是範例)
- 用戶可以使用 Http 來取得 HLS 影片。
Media Server 現在的選擇事實上很多,像以 nodejs 來說可以使用下面連結的這個,非常的簡單,而 nginx 它也有提供一些 media server 的套件。
nodejs-media-server nginx-rtmp-module nodejs-hls-server
接下來我們簡單的以 nodejs-hls-server 這個套件來實作個 Media Server。
1. 建立 Media Server
這個 Media Server 有兩件事情要處理。
- 可以將影片檔轉成 HLS 用的 .m3u8 檔。
- 用戶可以使用 Http 來使用 HLS 觀看影片。
首先咱們先來看看 Server 的部份,基本上程式碼很簡單,就像它套件裡面使用的,建立一個 Http Server 然後將 HLS 的套件附加到裡面。
// index.js
const HLSServer = require('hls-server')
const http = require('http')
const server = http.createServer()
const hls = new HLSServer(server, {
path: '/streams', // Base URI to output HLS streams
dir: 'source-m3u8' // Directory that input files are stored
})
server.listen(8000)
然後這裡還要做一件事情,那就是將 .mp4 影片檔轉換成 .m3u8 檔,這裡我們就需要使用到前一篇文章說的 ffmpeg 的神器,基本上程式碼如下,這裡我將套件裡的範例改成 async/await 的版本。
然後下面這段程式碼,就會將輸入的 .mp4 檔轉換成每 10 秒一段的 .ts 檔,然後最後在產生出 .m3u8 檔到你指定的位置。
const ffmpeg = require('fluent-ffmpeg')
module.exports = {
convertToHls: async (file) => {
return new Promise((resolve) => {
ffmpeg(file, { timeout: 432000 }).addOptions([
'-profile:v baseline', // for H264 video codec
'-level 3.0',
'-s 640x360', // 640px width, 360px height
'-start_number 0', // start the first .ts segment at index 0
'-hls_time 10', // 10 second segment duration
'-hls_list_size 0', // Maxmimum number of playlist entries)
'-f hls' // HLS format
]).output(`./source-m3u8/output.m3u8`).on('end', resolve).run()
});
}
}
上面這段要在 Server 啟動前先完成,使用範例如下:
// conver.js
const ffmpegHelper = require('./ffmpeg-helper’);
(async () => {
await ffmpegHelper.convertToHls(‘./source-mp4/input.mp4’);
})();
最要在執行以下兩段程式碼,然後就可以使用了。
node conver.js // 轉換成 .m3u8 檔
node index.js //啟動 server
然後到了這裡 Server 端,就準備才不多了。接下來就進入到用戶端。
使用 ffplay 測試
對了如果你在完成 server 以後,想要先測試一下你轉的 .m3u8 檔可不可以看,可以使用 ffplay 來測看看,執行完有看到影片就代表 ok !
ffplay http://127.0.0.1:8000/streams/output.m3u8
實作 - 網頁用戶端取得串流影像。
接下來咱們來建立一個可以在網頁上。
基本上要做的事情有以下幾件:
- 載入 hls.js,這樣才可以讓 audio 標籤直接使用 hls 連結。
- 讀取 hls 來源 ( hls.loadSource )。
- 讀取到以上就播放 ( video.play )。
<html>
<head><title>Test</title></head>
<body>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video controls id="video"></video>
<input type="text" />
<button id="load">Load</button>
<script>
if(Hls.isSupported()) {
var video = document.getElementById('video');
var hls = new Hls();
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function() {
video.play();
});
document.querySelector("#load").addEventListener("click", function () {
hls.loadSource(document.querySelector("input").value);
})
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.addEventListener('canplay',function() {
video.play();
});
document.querySelector("#load").addEventListener("click", function () {
video.src = document.querySelector("input").value;
})
}
</script>
</body>
</html>
執行結果如下圖。
結論
本篇文章中,咱們學習到如何建立最簡單可以動的點播功能,基本上重點就是三個功能。
- Media Server 可以處理 HLS 請求處理。
- Media Server 可以將不同格式的影片轉換 HLS 用的 .m3u8 (事實上這不一定要在 Media Server 處理)
- Client 要可以播放 HLS。
接下來下一篇文章咱們將要來學習如何建立一個直播功能
。