如何使用HTML5和WebRTC将网络摄像头广播到YouTube
在本文中,我们将解释 YouTube 直播如何工作,并展示拥有基本 JavaScript 知识的任何人如何使用 WebRTC 技术通过 HTML 页面进行 YouTube 直播。
您需要具备以下知识和技能
- JavaScript / HTML 基础知识
- 掌握一些 Linux 命令行使用技巧。
- 勤奋和能力。
YouTube 直播
YouTube 支持实时直播。也就是说,您不是上传视频,而是创建自己的实时直播,可以是您、您的猫、您的节目或任何其他表演。YouTube 直播工作室位于此页面。在 Google Chrome 中,它看起来如下
要启用直播,请点击启用直播按钮并完成两步验证。然后,按钮会变为创建直播活动,您就可以开始您的直播了。
点击立即开始直播即可直接进入直播。YouTube 会打开一个 Google Hangouts 窗口,所有流操作都在其中进行。
因此,我们在 YouTube 直播上创建了一个直播,开始了直播,然后停止了直播。结果,我们收到了包含该直播的 YouTube 视频。直播是通过 Google Hangouts 进行的。到目前为止听起来很棒,但根据IT 新闻,Google 将从 2017 年 4 月 25 日开始关闭用于视频应用开发的 Hangouts API。
对于开发者来说,这意味着我们将无法使用 Hangouts API 创建自己的自定义应用程序来传输视频(包括 YouTube)。
使用 RTMP 直播编码器进行直播
现在,让我们看一下不使用 Google Hangouts 进行直播的替代方法,该方法允许从专用设备(RTMP 直播编码器)传输视频流。
如果您点击“直播”按钮,您将看到熟悉的视频直播界面。现在重要的是 - 编码器设置
正如您所见,这里只有两个字段
- 服务器 URL
- 流名称/密钥
点击显示按钮后,将显示您的流名称,您可以复制它。
这些数据通常足以将视频流从 RTMP 直播编码器发送到 YouTube 直播,无需使用 Google Hangouts,无论身在何处,也无论使用什么计算机。(编码器设置)。RTMP 直播编码器(下称编码器)是捕获网络摄像头或专业摄像机视频流的硬件设备或软件,将其编码为 RTMP 协议并发送到指定地址。
为了生成高质量的音频和视频流,请使用标准的直播编码器编解码器,即视频使用 H.264,音频使用 AAC。这种组合是广为人知且可靠的,因此已成为独立编码器使用 RTMP 的事实标准。
例如,Adobe Flash Player 浏览器插件也是一个编码器,它可以直接从浏览器中的网页传输视频,但它不支持用于流式传输的 AAC 音频编解码器,因此由于缺少声音,通过它进行的直播受到一定限制。
因此,我们只考虑明确支持 H.264 和 AAC 编解码器的编码器。目前,我们知道有两个候选者可供测试,它们可以与这些编解码器一起工作
Adobe Flash Media Live Encoder (Mac OS 版) - Adobe 的免费软件编码器,能够将 RTMP 流编码为 H.264 和 AAC。请注意,AAC 音频编解码器仅在 Mac OS 的 FMLE 版本中受支持。如果您在 Windows 上使用相同的软件,则 AAC 编解码器不可用;将改用 mp3。
Wirecast - 一款付费编码器,有试用版,会在广播视频上叠加徽标,并每 30 秒插入一次声音。Wirecast 可安装在 Windows 上。
让我们从 Adobe FMLE 开始。在 Mac 上安装 FMLE,并将网络摄像头连接到计算机(我们在测试中使用了 Mac Mini)。FMLE 似乎无法与虚拟摄像头一起使用,因此您需要一个硬件 USB 网络摄像头或内置摄像头(如果您使用的是 Macbook)。
选择 H.264 作为视频编解码器,分辨率为 640x480。将音频编解码器保留为默认值,AAC 22050 Hz 单声道。所有其他 H.264 和 AAC 设置也应该能够完美运行。
在 FMS URL 框中输入从 YouTube 收到的直播 RTMP 地址。在 Stream 框中输入从 YouTube 收到的流名称。
* 该框名称很奇怪,FMS URL,因为 FMLE 认为世界上只有一个服务器能够接收 RTMP 流 - Adobe 的 Flash Media Server(现为 Adobe Media Server)。但正如我们所见,事实并非如此,包括 YouTube 在内的许多软件和服务都可以完美处理。
设置好所有设置后,我们点击绿色的开始按钮开始直播并将视频发送到 YouTube。图像有点模糊,因为我的测试 Mac 过载了,并且屏幕截图是用 Teamviewer 截取的,所以无法获得高质量图像。为了获得高质量的直播,请确保您拥有高分辨率摄像头和强大的 CPU,例如 Core i7,以及 SSD 硬盘,以便轻松无碍地编码 RTMP 视频流。
既然我们已经成功配置了 FMLE,就没有必要再显式测试 Wirecast。如果您在使用 FMLE 时遇到问题,或者只是附近没有 Mac OS,您可以尝试使用 Wirecast 进行相同的操作。
从 WebRTC 转换为 RTMP
上面,我们进行了一项测试,该测试显示了如何使用 YouTube 直播进行广播,以及如何将编码为 H.264 + AAC 的 RTMP 视频流发送到 YouTube。
现在,下一个任务是使用 WebRTC 完成同样的事情。WebRTC 是一项已内置于浏览器中的技术。它允许浏览器捕获摄像头视频和麦克风音频,并将流发送到网络。因此,支持 WebRTC 的浏览器可以像直播编码器一样工作 - 捕获和发送视频和声音。WebRTC 支持
- Chrome
- Firefox
- Opera
- Chrome for Android
- Firefox for Android
这意味着 WebRTC 视频流可以从桌面浏览器 Chrome、FF 以及这些浏览器的 Android 版本发送。
因此,我们的目标是在简单的 HTML 页面上实现从 Google Chrome 到 YouTube 的直播,而无需使用 Google Hangouts 或 RTMP 直播编码器。这里,我们有三个问题
- WebRTC 不支持 YouTube 所需的 RTMP 协议。
- WebRTC 不支持 YouTube 所需的 AAC 音频编解码器。
- Chrome 中的 WebRTC 不支持移动设备上的 H.264。它们使用 VP8。
由于这些原因,WebRTC 无法直接将音频+视频流发送到 YouTube 直播。说到 Adobe Flash Player,这里还有另一个问题
- 它不将音频编码为 AAC
因此,无论您使用的是支持 WebRTC 的浏览器(Chrome)还是带有 Flash Player 的浏览器(IE 或 Safari),您仍然无法直接从浏览器发送编码为 H.264 + AAC 的 RTMP 视频流。
解决方案是在服务器端转换视频流,如下所示: 这里,直播是通过一个媒介进行的 - 服务器接收 WebRTC 视频流并将其转换为 YouTube 可接受的格式。为了进行测试,我们使用 Web Call Server 5。
这是一个支持 WebRTC 和 RTMP 的媒体服务器,有试用版。
我们需要将 Web Call Server 5 安装到 Linux 服务器上,并将 WebRTC 视频流重定向到它。然后将流重定向到 YouTube。我们需要一个本地 64 位 Linux 服务器或 VPS 服务器。最低要求是 1 核 CPU、1GB RAM、Linux x86_64。
我们找到了一个陈旧的 2 核 Athlon 64,1.8 GHz,安装了 CentOS 6 和 2GB RAM。足够用于测试。安装过程在供应商网站上有详细记录。
1) 下载存档
wget https://flashphoner.com/download-wcs5-server.tar.gz
下载后,wget 会抱怨证书。所以我们必须设置标志
wget --no-check-certificate https://flashphoner.com/download-wcs5-server.tar.gz
2) 解压
tar -xzf download-wcs5-server.tar.gz
3) 运行安装程序
./install.sh
安装程序报告错误并指出缺少 Java。
4) 使用包管理器安装 Java,然后再次运行安装程序。
yum install java
./install.sh
安装过程中,安装程序会询问服务器是否在本地网络中。我们回答“是”,安装程序会将服务器的本地 IP 地址 192.168.1.59 写入设置。
5) 现在,是时候运行服务器了。
service webcallserver start
服务器大约需要一分钟才能启动。
6) 在 Chrome 中打开 https://192.168.1.59:8888 上的仪表板
果然,浏览器会抱怨缺少正常的 SSL 证书。稍后,我们可以导入它们。例如,我们可以从letsencrypt 获取免费的。
现在,我们只需点击“高级”/“继续”并确认安全排除。
7) 开发人员文档建议我们还要做一件事。我们需要为以下页面重复上一步:https://192.168.1.59:8443
这是使信号 WebSocket 连接正常工作所必需的。没有它们,WebRTC 将无法工作,因为它需要通过单独的连接进行 SDP 交换。
完成这两个步骤后,应该会打开带有演示示例的仪表板。我们需要一个名为“WebRTC 作为 RTMP 再发布”的演示,它看起来如下
让我们在 Google Chrome 中进行测试。目标是将 WebRTC 音频+视频流重定向到 Web Call Server 5,将其转换为 RTMP 并发送给接收者。
要开始测试,请点击开始按钮,并允许浏览器访问摄像头和麦克风。在上图
- 浏览器 Google Chrome 通过 websocket 协议和安全连接连接到 Web Call Server 5:wss://192.168.1.59:8443
- WebRTC 音频+视频流被发送到服务器,状态 PUBLISHING 表明视频流正在成功发送到服务器。
- Web Call Server 将收到的 WebRTC 音频+视频流发送到指定的 RTMP 地址
- rtmp://:1935/live
- stream1
所以,我们在这里将 RTMP 视频流转发到 localhost,即在本例中是同一个 192.168.1.59 服务器。因此,可以说 Web Call Server 接收了 WebRTC 流并将其作为 RTMP 转发回来。
请注意这与 YouTube 直播是如何对应的。在那里,我们指定了服务器 URL 和流名称/密钥
4) 然后,我们只需要在内置播放器中播放视频流。地址和流名称会自动生成。
页面内置的 RTMP 播放器非常简单,仅用于确保流存在并且播放正常。流的完整地址是:rtmp://192.168.1.59:1935/live/rtmp_stream1
请注意:Web Call Server 5 会在流名称前添加“rtmp_”前缀。也就是说,它会获取 stream1 流并将其转发为 rtmp_stream1。
在本地主机上进行测试时,流的名称必须不同。本地测试成功,因此是时候将流发送到 YouTube 直播了。请记住,当我们使用 RTMP 直播视频编码器测试 YouTube 直播时,我们使用了
- 服务器 URL:rtmp://a.rtmp.youtube.com/live2
- 流名称/密钥:myfm-c9td-etew-eqdf
也就是说,YouTube 只想要这个流名称:myfm-c9td-etew-eqdf。所以,如果 Web Call Server 添加了它的 rtmp_ 前缀,最终名称将是 rtmp_myfm-c9td-etew-eqdf,YouTube 将不会接受它。我们需要一个解决方法,所以让我们编辑服务器端的配置文件:/usr/local/FlashphonerWebCallServer/conf/flashphoner.properties。在配置文件中注释掉或删除此行
#rtmp_transponder_stream_name_prefix =rtmp_
这样,我们就告诉服务器不要添加前缀,而是按原样转发接收到的流。
更改此设置需要重新启动。所以,我们重新启动服务器并等待大约一分钟。
service webcallserver restart
重启后,我们就可以完成最后的步骤了。再次打开仪表板和“WebRTC 作为 RTMP 再发布”演示示例。但这次,我们输入 RTMP 地址,就像为直播编码器输入一样。
最后,我们打开 YouTube 直播并观看结果
这次我们能够将 WebRTC 视频流以 RTMP 格式发送到 YouTube 并获得画面。在 Google Chrome 浏览器中,在 chrome://webrtc-internals 选项卡上,您可以看到说明将 WebRTC 视频流传输到服务器的图表
从 YouTube 的角度来看,入站流量如下所示
看起来与 HTTP Live streaming (HLS) 非常相似,视频段通过 HTTP (HTTPS) 加载。太棒了!我们成功测试了所有内容并确保该方法有效。
我们有图像,我们有声音,视频流直接从浏览器流式传输到 YouTube。现在,让我们开始编码。特别是,我们希望在简单的 HTML 页面上实现同样的效果 - 我们的网站或应用程序的示例。
编码一个 HTML 页面以将 WebRTC 发送到 YouTube
理解示例的最简单方法是下载三个源文件:HTML、JavaScript、CSS。但是,我们将跳过捷径,从头开始创建一个最精简的虚拟页面。让我们首先创建一个模板 test-webrtc-youtube.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body></body>
</html>
现在,下载 flashphoner.js 脚本,它负责所有与 WebRTC 和向服务器发送视频流相关的操作。此脚本是 Web SDK 的一部分,可以从此处下载。
下载并解压 Web SDK 到已安装 Apache(或 Nginx)的单独服务器上。
wget https://flashphoner.com/downloads/builds/flashphoner_client/wcs_api-2.0/flashphoner-api-0.5.14.1977-48448b99eddb0da1248519290dba2d4d00d4a505.tar.gz
创建文件夹 /var/www/html/test-webrtc-youtube,其中应包含 html 页面,并将 html 和 js 文件复制到那里。因此,我们得到以下结构
test-webrtc-youtube
-- flashphoner.js
-- test-webrtc-youtube.html
1. 向页面添加以下元素
<body onload="init_page()">
<div id="localVideo" style="width:320px;height:320px;border: 1px solid"></div>
Server URL <input type="text" id="urlServer" value="wss://192.168.1.59:8443"/><br/>
Stream URL: <input type="text" id="rtmpUrl" value="rtmp://a.rtmp.youtube.com/live2"/><br/>
Stream name / key: <input type="text" id="streamName" value="myfm-c9td-etew-xxxx"/><br/>
<input type="button" onclick="publishToYoutube()" value="Start"/>
<p id="status"></p>
</body
1) localVideo - 这是一个用于显示网络摄像头视频的 div
2) urlServer、rtmpUrl、streamName - 前面测试中已知的变量
3) status - 此字段显示连接状态或流状态
2. 添加三个变量
var SESSION_STATUS = Flashphoner.constants.SESSION_STATUS;
var STREAM_STATUS = Flashphoner.constants.STREAM_STATUS;
var localVideo;
前两个是快捷方式。localVideo 变量将保存指向 div 元素的链接。
3. 初始化 API
function init_page() {
Flashphoner.init();
localVideo = document.getElementById("localVideo");
}
4. 连接到 WCS 服务器并开始流式传输。
function publishToYoutube(){
var urlServer = document.getElementById("urlServer").value;
Flashphoner.createSession({urlServer: urlServer}).on(SESSION_STATUS.ESTABLISHED, function(session){
//session connected, start streaming
startStreaming(session);
}).on(SESSION_STATUS.DISCONNECTED, function(){
setStatus("Connection DISCONNECTED");
}).on(SESSION_STATUS.FAILED, function(){
setStatus("Connection FAILED");
});
}
在连接成功(由 ESTABLISHED 事件指示)后,我们通过调用 startStreaming 函数来开始流式传输。
5. 发送视频流。
function startStreaming(session) {
var streamName = document.getElementById("streamName").value;
var rtmpUrl = document.getElementById("rtmpUrl").value;
session.createStream({
name: streamName,
display: localVideo,
cacheLocalResources: true,
receiveVideo: false,
receiveAudio: false,
rtmpUrl: rtmpUrl
}).on(STREAM_STATUS.PUBLISHING, function(publishStream){
setStatus(STREAM_STATUS.PUBLISHING);
}).on(STREAM_STATUS.UNPUBLISHED, function(){
setStatus(STREAM_STATUS.UNPUBLISHED);
}).on(STREAM_STATUS.FAILED, function(){
setStatus(STREAM_STATUS.FAILED);
}).publish();
}
在这里,我们创建流并为其调用 publish 函数。
6. 使用单独的函数显示所有状态。
function setStatus(status){
document.getElementById("status").innerHTML = status;
}
最后,我们得到了与演示几乎相同的结果
请注意,我们再次使用了 https 协议。Web 服务器必须配置为通过 https 工作。通常,这只需要设置 mod_ssl。
yum install mod_ssl
页面的 HTML 代码正好是 65 行。它看起来如下
源文件已附上。结果,我们得到一个 65 行的 HTML 页面(包括所有脚本),该页面使用 API 文件 flashphoner.js 将 WebRTC 视频发送到 Web Call Server,而 Web Call Server 再将该视频流转发到 YouTube 直播服务。
就是这样。本文使用的材料和链接如下,供希望重现所有步骤的人参考。
链接
1) Youtube 直播
2) Adobe Flash Media Live Encoder
3) Wirecast
4) Web Call Server (使用了版本 2047)
5) WebRTC
6) Google 关闭 Hangouts API