当前位置: 首页 > news >正文

网站看不到排版怎么办wordpress博客主题修改

网站看不到排版怎么办,wordpress博客主题修改,阿里云做网站送服务器吗,重庆有哪些地方在本教程中#xff0c;您将构建一个视频广播应用程序#xff0c;该应用程序在 Golang 中读取摄像头并将其发送到 ION-SFU#xff08;选择性转发单元#xff09;#xff0c;从而使 WebRTC 会话更有效地扩展。 WebRTC 是 Web Real-Time Communication 的缩写#xff0c;是…在本教程中您将构建一个视频广播应用程序该应用程序在 Golang 中读取摄像头并将其发送到 ION-SFU选择性转发单元从而使 WebRTC 会话更有效地扩展。 WebRTC 是 Web Real-Time Communication 的缩写是一种利用点对点连接在网络上实现实时音频、视频和数据传输的通信协议。 WebRTC 还提供了大多数浏览器默认提供的 Javascript API可帮助开发人员在其应用程序中实现该协议。但是也有一些其他语言的 WebRTC 协议的实现。 在本教程中您将构建一个视频广播应用程序该应用程序在 Golang 中读取摄像头并将其发送到 ION-SFU选择性转发单元从而使 WebRTC 会话更有效地扩展。 该应用程序还将配备一个小型前端让您可以通过从 ION-SFU 服务器读取您发布的视频来观看它。 目录 先决条件 技术栈 设置 ION-SFU 创建项目 建立 WebRTC 连接 客户端 Ion-SDK-Go 结论 先决条件 在开始本指南之前您需要具备以下条件 有效的 Golang 安装。 连接到计算机的摄像头可以使用 Video for Linux 作为视频流的来源进行读取。 可选如果你想连接不在你网络上的设备你需要在你的应用程序中添加一个 TURN 服务器。如果您想了解更多关于 TURN 的信息以及如何设置您自己的 TURN。 技术栈 现在您已经大致了解了要构建的内容让我们仔细看看正在使用的工具以及它们如何相互协作。 让我们分解不同的组件 Pion -WebRTC 协议的纯 Golang 实现。用于与 ION-SFU 建立对等连接并发送视频流。 ION SFU -ION SFU选择性转发单元是一种视频路由服务可让 Webrtc 会话更有效地扩展。 Pion mediadevices – Mediadevices API的 Golang 实现用于将相机读取为可以使用对等连接发送的媒体流。 这样做的一个主要好处是您无需打开浏览器选项卡即可读取相机。使用选择性转发单元也将有助于提高性能并为大量用户扩展应用程序。 设置 ION-SFU 在本节中您将克隆和配置 ION-SFU 服务器以便您可以将其用于您的应用程序。 首先您将克隆存储库以便拥有开始设置选择性转发单元所需的所有资源 git clone --branch v1.10.6 https://github.com/pion/ion-sfu.git 此命令将从 Github 克隆 ION-SFU 存储库并在您的目录中创建一个名为ion-sfu的文件夹。现在使用以下命令进入目录 cd ion-sfu 接下来您可以通过更改config.toml文件来编辑 sfu 的配置。标准配置适合测试和本地使用但如果您尝试从另一个网络中的设备访问服务器我建议添加 STUN 和 TURN 服务器。 完成配置后您可以使用以下命令启动服务器 go build ./cmd/signal/json-rpc/main.go ./main -c config.toml或者如果您更喜欢使用 Golang 启动服务器也可以使用 Docker 启动服务器。 docker run -p 7000:7000 -p 5000-5020:5000-5020/udp pionwebrtc/ion-sfu:v1.10.6-jsonrpc您现在已经成功设置了 ION-SFU 服务器应该会在控制台中看到以下输出。 config config.toml load ok! [2020-10-12 19:04:19.017] [INFO] [376][main.go][main] — Starting SFU Node — [2020-10-12 19:04:19.018] [INFO] [410][main.go][main] Listening at http://[:7000] 创建项目 现在 ion-sfu 服务器的设置和配置已经完成是时候创建项目了 首先您需要创建一个目录并进入该目录。 mkdir mediadevice-broadcast cd mediadevice-broadcast 之后您可以使用以下命令继续创建项目所需的所有文件 mkdir public touch main.go public/index.html public/index.js public/style.css 跟随本文还需要安装两个包。 sudo apt-get install -y v4l-utils sudo apt-get install -y libvpx-dev 如果您不在 Linux 上则可能需要下载不同的软件包。查看媒体设备文档以获取更多信息。 建立 WebRTC 连接 在使用 WebRTC 交换任何数据之前必须首先在两个 WebRTC 代理之间建立对等连接。由于点对点连接通常不能直接建立因此需要一些信令方法。 发送给 ion-sfu 的信号将通过 Websockets 协议处理。为此我们将使用连接到 Websockets 服务器的gorilla/websocket库实现一个简单的 Websockets 样板并允许我们接收传入消息并发送我们自己的消息。 p ackage mainimport (bytesencoding/jsonflagfmtiolognet/urlgithub.com/google/uuidgithub.com/gorilla/websocket )var addr stringfunc main() {flag.StringVar(addr, a, localhost:7000, address to use)flag.Parse()u : url.URL{Scheme: ws, Host: addr, Path: /ws}log.Printf(connecting to %s, u.String())c, _, err : websocket.DefaultDialer.Dial(u.String(), nil)if err ! nil {log.Fatal(dial:, err)}defer c.Close()// Read incoming Websocket messagesdone : make(chan struct{})go readMessage(c, done)-done }func readMessage(connection *websocket.Conn, done chan struct{}) {defer close(done)for {_, message, err : connection.ReadMessage()if err ! nil || err io.EOF {log.Fatal(Error reading: , err)break}fmt.Printf(recv: %s, message)} }现在让我们浏览一下代码以便更好地理解 该标志用于在启动脚本时动态提供 Websockets 服务器的 URL标准值为localhost:7000 该 URL 用于使用Dial方法创建 Websockets 客户端。然后我们检查连接是否导致错误如果是这样则打印日志。 readMessage函数然后通过在 Websocket 连接上调用ReadMessage()来读取传入的消息并作为 Go 例程运行因此它不会阻塞主线程并且可以在后台运行。 main()函数的最后一行确保脚本在done变量未关闭时运行。 下一步是创建到 ion-sfu 的对等连接并处理传入的 WebRTC 信号事件。 var peerConnection *webrtc.PeerConnectionfunc main() { ...config : webrtc.Configuration{ICEServers: []webrtc.ICEServer{{URLs: []string{stun:stun.l.google.com:19302},},/*{URLs: []string{turn:TURN_IP:3478?transporttcp},Username: username,Credential: password,},*/},SDPSemantics: webrtc.SDPSemanticsUnifiedPlanWithFallback,}// Create a new RTCPeerConnectionmediaEngine : webrtc.MediaEngine{}vpxParams, err : vpx.NewVP8Params()if err ! nil {panic(err)}vpxParams.BitRate 500_000 // 500kbpscodecSelector : mediadevices.NewCodecSelector(mediadevices.WithVideoEncoders(vpxParams),)codecSelector.Populate(mediaEngine)api : webrtc.NewAPI(webrtc.WithMediaEngine(mediaEngine))peerConnection, err api.NewPeerConnection(config)if err ! nil {panic(err)}}在这里我们首先创建一个 WebRTC 配置我们在其中定义将在信令过程中使用的 STUN 和 TURN 服务器。之后我们创建一个MediaEngine让我们定义对等连接支持的编解码器。 完成所有这些配置后我们可以通过在我们刚刚创建的 WebRTC API 上调用NewPeerConnection函数来创建新的对等连接。 在通过 Websockets 将报价发送到 ion-sfu 服务器之前我们首先需要添加视频和音频流。这是媒体设备库发挥作用以从摄像机读取视频的地方。 fmt.Println(mediadevices.EnumerateDevices())s, err : mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{Video: func(c *mediadevices.MediaTrackConstraints) {c.FrameFormat prop.FrameFormat(frame.FormatYUY2)c.Width prop.Int(640)c.Height prop.Int(480)},Codec: codecSelector,})if err ! nil {panic(err)}for _, track : range s.GetTracks() {track.OnEnded(func(err error) {fmt.Printf(Track (ID: %s) ended with error: %v\n,track.ID(), err)})_, err peerConnection.AddTransceiverFromTrack(track,webrtc.RtpTransceiverInit{Direction: webrtc.RTPTransceiverDirectionSendonly,},)if err ! nil {panic(err)}}使用对等连接创建媒体设备库的实例后您可以使用GetUserMedia函数并传递参数来获取用户媒体。 您可能需要进行的一项配置更改是更改 FrameFormat以支持您连接的相机。您可以使用以下命令检查相机的帧格式 v4l2-ctl --all 所有支持的格式也可以在媒体设备 Github 存储库中找到。 现在可以创建报价并将其保存到对等连接的本地描述中。 // Creating WebRTC offer offer, err : peerConnection.CreateOffer(nil) // Set the remote SessionDescription err peerConnection.SetLocalDescription(offer) if err ! nil { panic(err) } 下一步是使用 Websockets 将报价发送到 sfu。Websockets 消息是 JSON需要特定的结构才能被 sfu 识别。 因此我们需要创建一个结构来保存我们的报价和指定我们想要加入的房间的所需 sid然后我们可以将其转换为 JSON。 type SendOffer struct {SID string json:sidOffer *webrtc.SessionDescription json:offer }现在我们使用json.Marshal()函数将报价对象转换为 JSON 然后使用 JSON 报价对象作为请求中的参数。 将请求转换为字节数组后消息最终可以使用WriteMessage()函数通过 Websockets 发送。 offerJSON, err : json.Marshal(SendOffer{ Offer: peerConnection.LocalDescription(), SID: “test room”, }) params : (*json.RawMessage)(offerJSON) connectionUUID : uuid.New() connectionID uint64(connectionUUID.ID()) offerMessage : jsonrpc2.Request{ Method: “join”, Params: params, ID: jsonrpc2.ID{ IsString: false, Str: “”, Num: connectionID, }, } reqBodyBytes : new(bytes.Buffer) json.NewEncoder(reqBodyBytes).Encode(offerMessage) messageBytes : reqBodyBytes.Bytes() c.WriteMessage(websocket.TextMessage, messageBytes) 现在报价已发送我们需要正确响应 WebRTC 事件和来自 Websockets 服务器的响应。 每当找到新的 ICE 候选对象时都会调用OnICECandidate事件。然后使用该方法通过向 sfu 发送 trickle 请求来协商与远程对等方的连接。 // Handling OnICECandidate event peerConnection.OnICECandidate(func(candidate *webrtc.ICECandidate) { if candidate ! nil { candidateJSON, err : json.Marshal(Candidate{ Candidate: candidate, Target: 0, }) params : (*json.RawMessage)(candidateJSON)if err ! nil {log.Fatal(err)}message : jsonrpc2.Request{Method: trickle,Params: params,}reqBodyBytes : new(bytes.Buffer)json.NewEncoder(reqBodyBytes).Encode(message)messageBytes : reqBodyBytes.Bytes()c.WriteMessage(websocket.TextMessage, messageBytes) }}) peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { fmt.Printf(“Connection State has changed to %s \n”, connectionState.String()) }) 之前创建的readMessage函数用于接收和响应 sfu 发送的传入 Websockets 消息。 为此我们首先需要创建包含接收到的消息的结构以便我们可以使用数据。然后我们将确定消息是针对哪个事件并相应地处理它们。 // SendAnswer object to send to the sfu over Websockets type SendAnswer struct {SID string json:sidAnswer *webrtc.SessionDescription json:answer }type ResponseCandidate struct {Target int json:targetCandidate *webrtc.ICECandidateInit json:candidate }// TrickleResponse received from the sfu server type TrickleResponse struct {Params ResponseCandidate json:paramsMethod string json:method }// Response received from the sfu over Websockets type Response struct {Params *webrtc.SessionDescription json:paramsResult *webrtc.SessionDescription json:resultMethod string json:methodId uint64 json:id }func readMessage(connection *websocket.Conn, done chan struct{}) {defer close(done)for {_, message, err : connection.ReadMessage()if err ! nil || err io.EOF {log.Fatal(Error reading: , err)break}fmt.Printf(recv: %s, message)var response Responsejson.Unmarshal(message, response)if response.Id connectionID {result : *response.ResultremoteDescription response.Resultif err : peerConnection.SetRemoteDescription(result); err ! nil {log.Fatal(err)}} else if response.Id ! 0 response.Method offer {peerConnection.SetRemoteDescription(*response.Params)answer, err : peerConnection.CreateAnswer(nil)if err ! nil {log.Fatal(err)}peerConnection.SetLocalDescription(answer)connectionUUID : uuid.New()connectionID uint64(connectionUUID.ID())offerJSON, err : json.Marshal(SendAnswer{Answer: peerConnection.LocalDescription(),SID: test room,})params : (*json.RawMessage)(offerJSON)answerMessage : jsonrpc2.Request{Method: answer,Params: params,ID: jsonrpc2.ID{IsString: false,Str: ,Num: connectionID,},}reqBodyBytes : new(bytes.Buffer)json.NewEncoder(reqBodyBytes).Encode(answerMessage)messageBytes : reqBodyBytes.Bytes()connection.WriteMessage(websocket.TextMessage, messageBytes)} else if response.Method trickle {var trickleResponse TrickleResponseif err : json.Unmarshal(message, trickleResponse); err ! nil {log.Fatal(err)}err : peerConnection.AddICECandidate(*trickleResponse.Params.Candidate)if err ! nil {log.Fatal(err)}}} }如您所见我们正在处理两个不同的事件 Offer – sfu 发送一个 offer我们通过将发送的 offer 保存到我们对等连接的远程描述中并发回一个带有本地描述的答案来做出反应这样我们就可以连接到远程对等点。 涓流 – sfu 发送一个新的 ICE 候选者我们将其添加到对等连接 所有这些配置将产生以下文件 package mainimport (bytesencoding/jsonflagfmtiolognet/urlgithub.com/google/uuidgithub.com/gorilla/websocketgithub.com/pion/mediadevicesgithub.com/pion/mediadevices/pkg/codec/vpxgithub.com/pion/mediadevices/pkg/framegithub.com/pion/mediadevices/pkg/propgithub.com/pion/webrtc/v3github.com/sourcegraph/jsonrpc2// Note: If you dont have a camera or microphone or your adapters are not supported,// you can always swap your adapters with our dummy adapters below.// _ github.com/pion/mediadevices/pkg/driver/videotest// _ github.com/pion/mediadevices/pkg/driver/audiotest_ github.com/pion/mediadevices/pkg/driver/camera // This is required to register camera adapter_ github.com/pion/mediadevices/pkg/driver/microphone // This is required to register microphone adapter )type Candidate struct {Target int json:targetCandidate *webrtc.ICECandidate json:candidate }type ResponseCandidate struct {Target int json:targetCandidate *webrtc.ICECandidateInit json:candidate }// SendOffer object to send to the sfu over Websockets type SendOffer struct {SID string json:sidOffer *webrtc.SessionDescription json:offer }// SendAnswer object to send to the sfu over Websockets type SendAnswer struct {SID string json:sidAnswer *webrtc.SessionDescription json:answer }// TrickleResponse received from the sfu server type TrickleResponse struct {Params ResponseCandidate json:paramsMethod string json:method }// Response received from the sfu over Websockets type Response struct {Params *webrtc.SessionDescription json:paramsResult *webrtc.SessionDescription json:resultMethod string json:methodId uint64 json:id }var peerConnection *webrtc.PeerConnection var connectionID uint64 var remoteDescription *webrtc.SessionDescriptionvar addr stringfunc main() {flag.StringVar(addr, a, localhost:7000, address to use)flag.Parse()u : url.URL{Scheme: ws, Host: addr, Path: /ws}log.Printf(connecting to %s, u.String())c, _, err : websocket.DefaultDialer.Dial(u.String(), nil)if err ! nil {log.Fatal(dial:, err)}defer c.Close()config : webrtc.Configuration{ICEServers: []webrtc.ICEServer{{URLs: []string{stun:stun.l.google.com:19302},},/*{URLs: []string{turn:TURN_IP:3478},Username: username,Credential: password,},*/},SDPSemantics: webrtc.SDPSemanticsUnifiedPlanWithFallback,}// Create a new RTCPeerConnectionmediaEngine : webrtc.MediaEngine{}vpxParams, err : vpx.NewVP8Params()if err ! nil {panic(err)}vpxParams.BitRate 500_000 // 500kbpscodecSelector : mediadevices.NewCodecSelector(mediadevices.WithVideoEncoders(vpxParams),)codecSelector.Populate(mediaEngine)api : webrtc.NewAPI(webrtc.WithMediaEngine(mediaEngine))peerConnection, err api.NewPeerConnection(config)if err ! nil {panic(err)}// Read incoming Websocket messagesdone : make(chan struct{})go readMessage(c, done)fmt.Println(mediadevices.EnumerateDevices())s, err : mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{Video: func(c *mediadevices.MediaTrackConstraints) {c.FrameFormat prop.FrameFormat(frame.FormatYUY2)c.Width prop.Int(640)c.Height prop.Int(480)},Codec: codecSelector,})if err ! nil {panic(err)}for _, track : range s.GetTracks() {track.OnEnded(func(err error) {fmt.Printf(Track (ID: %s) ended with error: %v\n,track.ID(), err)})_, err peerConnection.AddTransceiverFromTrack(track,webrtc.RtpTransceiverInit{Direction: webrtc.RTPTransceiverDirectionSendonly,},)if err ! nil {panic(err)}}// Creating WebRTC offeroffer, err : peerConnection.CreateOffer(nil)// Set the remote SessionDescriptionerr peerConnection.SetLocalDescription(offer)if err ! nil {panic(err)}// Handling OnICECandidate eventpeerConnection.OnICECandidate(func(candidate *webrtc.ICECandidate) {if candidate ! nil {candidateJSON, err : json.Marshal(Candidate{Candidate: candidate,Target: 0,})params : (*json.RawMessage)(candidateJSON)if err ! nil {log.Fatal(err)}message : jsonrpc2.Request{Method: trickle,Params: params,}reqBodyBytes : new(bytes.Buffer)json.NewEncoder(reqBodyBytes).Encode(message)messageBytes : reqBodyBytes.Bytes()c.WriteMessage(websocket.TextMessage, messageBytes)}})peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {fmt.Printf(Connection State has changed to %s \n, connectionState.String())})offerJSON, err : json.Marshal(SendOffer{Offer: peerConnection.LocalDescription(),SID: test room,})params : (*json.RawMessage)(offerJSON)connectionUUID : uuid.New()connectionID uint64(connectionUUID.ID())offerMessage : jsonrpc2.Request{Method: join,Params: params,ID: jsonrpc2.ID{IsString: false,Str: ,Num: connectionID,},}reqBodyBytes : new(bytes.Buffer)json.NewEncoder(reqBodyBytes).Encode(offerMessage)messageBytes : reqBodyBytes.Bytes()c.WriteMessage(websocket.TextMessage, messageBytes)-done }func readMessage(connection *websocket.Conn, done chan struct{}) {defer close(done)for {_, message, err : connection.ReadMessage()if err ! nil || err io.EOF {log.Fatal(Error reading: , err)break}fmt.Printf(recv: %s, message)var response Responsejson.Unmarshal(message, response)if response.Id connectionID {result : *response.ResultremoteDescription response.Resultif err : peerConnection.SetRemoteDescription(result); err ! nil {log.Fatal(err)}} else if response.Id ! 0 response.Method offer {peerConnection.SetRemoteDescription(*response.Params)answer, err : peerConnection.CreateAnswer(nil)if err ! nil {log.Fatal(err)}peerConnection.SetLocalDescription(answer)connectionUUID : uuid.New()connectionID uint64(connectionUUID.ID())offerJSON, err : json.Marshal(SendAnswer{Answer: peerConnection.LocalDescription(),SID: test room,})params : (*json.RawMessage)(offerJSON)answerMessage : jsonrpc2.Request{Method: answer,Params: params,ID: jsonrpc2.ID{IsString: false,Str: ,Num: connectionID,},}reqBodyBytes : new(bytes.Buffer)json.NewEncoder(reqBodyBytes).Encode(answerMessage)messageBytes : reqBodyBytes.Bytes()connection.WriteMessage(websocket.TextMessage, messageBytes)} else if response.Method trickle {var trickleResponse TrickleResponseif err : json.Unmarshal(message, trickleResponse); err ! nil {log.Fatal(err)}err : peerConnection.AddICECandidate(*trickleResponse.Params.Candidate)if err ! nil {log.Fatal(err)}}} }注意您可能需要启用 go modules 以便在启动脚本时自动下载依赖项。 现在可以使用以下命令启动完成的脚本 You might need to add sudo to access your camera go run main.go 您应该看到以下输出 recv: {method:trickle,params:{candidate:candidate:3681230645 1 udp 2130706431 10.0.0.35 49473 typ host,sdpMid:,sdpMLineIndex:0,usernameFragment:null},jsonrpc:2.0} recv: {method:trickle,params:{candidate:candidate:233762139 1 udp 2130706431 172.17.0.1 57218 typ host,sdpMid:,sdpMLineIndex:0,usernameFragment:null},jsonrpc:2.0} Connection State has changed to checking recv: {method:trickle,params:{candidate:candidate:2890797847 1 udp 2130706431 172.22.0.1 41179 typ host,sdpMid:,sdpMLineIndex:0,usernameFragment:null},jsonrpc:2.0} recv: {method:trickle,params:{candidate:candidate:3528925834 1 udp 2130706431 172.18.0.1 58906 typ host,sdpMid:,sdpMLineIndex:0,usernameFragment:null},jsonrpc:2.0} recv: {method:trickle,params:{candidate:candidate:3197649470 1 udp 1694498815 212.197.155.248 36942 typ srflx raddr 0.0.0.0 rport 36942,sdpMid:,sdpMLineIndex:0,usernameFragment:null},jsonrpc:2.0} recv: {method:trickle,params:{candidate:candidate:2563076625 1 udp 16777215 104.248.140.156 11643 typ relay raddr 0.0.0.0 rport 42598,sdpMid:,sdpMLineIndex:0,usernameFragment:null},jsonrpc:2.0} Connection State has changed to connected 客户端 现在我们已经成功地将视频从摄像机发送到 sfu是时候创建一个前端来接收它了。 HTML 文件非常基本只包含一个视频对象和一个订阅流的按钮。它还会将当前的 WebRTC 日志打印到一个 div 中。 !DOCTYPE html html langen headmeta charsetutf-8/metanameviewportcontentwidthdevice-width, initial-scale1, shrink-to-fitno/style#remotes video {width: 320px;}/styletitleWebRTC test frontend/title /head body divdiv idremotesspanstyleposition: absolute; margin-left: 5px; margin-top: 5pxclassbadge badge-primaryRemotes/span/div /divscript srchttps://unpkg.com/ion-sdk-js1.5.5/dist/ion-sdk.min.js/script script srchttps://unpkg.com/ion-sdk-js1.5.5/dist/json-rpc.min.js/script script srcindex.js/script /body /html然后 javascript 文件将连接到 sfu类似于上面的 Golang 脚本。唯一的区别是它不是读取相机并将视频发送到 sfu而是接收视频。 我不会详细介绍因为上面已经涵盖了所有功能。 const remotesDiv document.getElementById(remotes);const config {codec: vp8,iceServers: [{urls: stun:stun.l.google.com:19302,},/*{urls: turn:TURN_IP:3468,username: username,credential: password},*/] };const signalLocal new Signal.IonSFUJSONRPCSignal(ws://127.0.0.1:7000/ws );const clientLocal new IonSDK.Client(signalLocal, config); signalLocal.onopen () clientLocal.join(test room);clientLocal.ontrack (track, stream) {console.log(got track, track.id, for stream, stream.id);if (track.kind video) {track.onunmute () {const remoteVideo document.createElement(video);remoteVideo.srcObject stream;remoteVideo.autoplay true;remoteVideo.muted true;remotesDiv.appendChild(remoteVideo);track.onremovetrack () remotesDiv.removeChild(remoteVideo);};} };在这里您唯一需要记住的是如果不提供或请求某种流就无法发送对等连接。这就是为什么在发送报价之前添加两个接收器一个用于音频一个用于视频。 您现在可以通过在浏览器中打开 HTML 文件来启动前端。或者您可以通过在项目的根目录中创建一个新文件来使用 Express 服务器打开 HTML 文件。 touch server.js 在添加代码之前需要安装 express 依赖项。 npm init -y npm install express --save 然后您可以使用以下代码将前端作为静态站点运行。 const express require(express); const app express();const port 3000;const http require(http); const server http.createServer(app);app.use(express.static(__dirname /public));server.listen(port, () console.log(Server is running on port ${port}));使用以下命令启动应用程序。 node server.js您现在应该能够访问本地计算机的 localhost:3000 上的前端。 Ion-SDK-Go 如上所述同样的视频流功能也可以使用ion 团队创建的库来实现它抽象了 WebRTC 信号因此使实现更短、更简洁。不过知道如何自己实现信号非常重要并且可以让您为更复杂的项目进行更多定制。 package mainimport (flagfmtilog github.com/pion/ion-logsdk github.com/pion/ion-sdk-gogithub.com/pion/mediadevicesgithub.com/pion/mediadevices/pkg/codec/vpxgithub.com/pion/mediadevices/pkg/framegithub.com/pion/mediadevices/pkg/propgithub.com/pion/webrtc/v3// Note: If you dont have a camera or microphone or your adapters are not supported,// you can always swap your adapters with our dummy adapters below.// _ github.com/pion/mediadevices/pkg/driver/videotest// _ github.com/pion/mediadevices/pkg/driver/audiotest_ github.com/pion/mediadevices/pkg/driver/camera // This is required to register camera adapter_ github.com/pion/mediadevices/pkg/driver/microphone // This is required to register microphone adapter )var (log ilog.NewLoggerWithFields(ilog.DebugLevel, , nil) )func main() {// parse flagvar session, addr stringflag.StringVar(addr, addr, localhost:50051, Ion-sfu grpc addr)flag.StringVar(session, session, test room, join session name)flag.Parse()// add stun serverswebrtcCfg : webrtc.Configuration{ICEServers: []webrtc.ICEServer{webrtc.ICEServer{URLs: []string{stun:stun.stunprotocol.org:3478, stun:stun.l.google.com:19302},},},}config : sdk.Config{Log: log.Config{Level: debug,},WebRTC: sdk.WebRTCTransportConfig{Configuration: webrtcCfg,},}// new sdk enginee : sdk.NewEngine(config)// get a client from enginec, err : sdk.NewClient(e, addr, client id)c.GetPubTransport().GetPeerConnection().OnICEConnectionStateChange(func(state webrtc.ICEConnectionState) {log.Infof(Connection state changed: %s, state)})if err ! nil {log.Errorf(client err%v, err)panic(err)}e.AddClient(c)// client join a sessionerr c.Join(session, nil)if err ! nil {log.Errorf(join err%v, err)panic(err)}vpxParams, err : vpx.NewVP8Params()if err ! nil {panic(err)}vpxParams.BitRate 500_000 // 500kbpscodecSelector : mediadevices.NewCodecSelector(mediadevices.WithVideoEncoders(vpxParams),)fmt.Println(mediadevices.EnumerateDevices())s, err : mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{Video: func(c *mediadevices.MediaTrackConstraints) {c.FrameFormat prop.FrameFormat(frame.FormatYUY2)c.Width prop.Int(640)c.Height prop.Int(480)},Codec: codecSelector,})if err ! nil {panic(err)}for _, track : range s.GetTracks() {track.OnEnded(func(err error) {fmt.Printf(Track (ID: %s) ended with error: %v\n,track.ID(), err)})_, err c.Publish(track)if err ! nil {panic(err)} else {break // only publish first track, thanks}}select {} }如您所见该库处理信号因此抽象了我们上面编写的大量代码。该库与我们上面实现的代码之间的一个区别是该库使用 GRPC 进行信号传输而我们使用 JSONRPC。因此您必须以 AllRPC 模式而不是 JSONRPC 模式启动 ion-sfu。这可以通过使用 Golang 启动 AllRPC 版本或在使用 Docker 时使用AllRPC 图像标签例如 latest-allrpc来完成。 您现在可以使用 go run 命令启动应用程序 go run ./main.go 您现在应该还可以在本地机器的 localhost:3000 上看到您的摄像头的视频。 结论 在本文中您了解了什么是 sfu 以及如何利用 ion-sfu 构建视频广播应用程序。您还学习了如何使用 Golang 媒体设备库在不打开浏览器窗口的情况下读取您的摄像头。 作者Gabriel Tanner 原文链接https://gabrieltanner.org/blog/broadcasting-ion-sfu/ https://www.nxrte.com/jishu/webrtc/14792.html
http://www.zqtcl.cn/news/330555/

相关文章:

  • 淘宝客做网站怎样推广空间购买后打不开网站
  • 信阳网站设计银川网站建设nx110
  • 建设安全协会网站58招聘运营网站怎么做
  • 做原创的网站做游戏平面设计好的素材网站有哪些
  • 校园网站wordpress 防攻击插件
  • wordpress 更好的主题丁的老头seo博客
  • 上海市工程信息网站北京专业网站翻译影音字幕翻译速记速记速记速而高效
  • 网站建设心得体会500字网页制作三剑客是指什么
  • 大连做网站优化一级a做爰片 网站就能看
  • 网站优化页面中山seo网络推广
  • 建设网站一定要数据库吗湖北百度seo
  • 下载了wordpress然后怎么用怎样健建设一个有利于优化的网站
  • 网站开发心得500字做代售机票网站程序
  • php电影网站开发凡诺网站建设
  • 兰州道路建设情况网站南宁网站开发
  • 网站开发服务费投资者网站建设
  • 网站开发 如何备案新站点seo联系方式
  • 自动全屏网站模板贵州网站制作公司电话
  • 南昌购物网站制作国外免费网站空间
  • 网站地图模版企业做网站etp和源程序
  • 电子商务企业网站的推广方式外贸长尾关键词挖掘网站
  • 靓号网建站网站商城html模板
  • 广东顺德网站建设wordpress 我爱搜罗网
  • 基金网站建设需求书昆明网站制作工具
  • 京东网上购物商城官方网站国外网站页头设计图片
  • 芯片设计公司排名安卓优化大师app
  • 如何进行网站域名解析网站开发的工作方法
  • 专门做衣服的网站有哪些南宁企业官网seo
  • 网站 建设 内容中铁建设集团有限公司招聘官网
  • 个人电脑做服务器网站cn域名注册流程