增加物流的配置文件

http_chanel
yiming 3 years ago
parent cdd255edda
commit be05b7e151

@ -1,88 +1,20 @@
# RTSPtoWebRTC
RTSP Stream to WebBrowser over WebRTC based on Pion
## 根据github上一个项目修改地址 https://github.com/deepch/RTSPtoWebRTC
full native! not use ffmpeg or gstreamer
## 先知
1. 物流项目会配置球机其中球机有个配置是视频流IP,该配置是视频流解码并推流的地址,也就是该服务的地址
2. 物流web会向该服务拉流播放球机视频直播
## 项目启动后的流程说明
1. config.go文件的loadConfig()会读取application.yml读取物流JAVA服务地址JavaServer和本机的IPLocalIp
2. 发起http请求到物流java服务的/api/camera/rtcConfig接口读取球机的配置。注意只会读取视频流IP为本机的球机配置。http://{JavaServer}/api/camera/rtcConfig?rtcServer={LocalIp}
3. 本服务端口为8083不要修改
if you need RTSPtoWSMP4f use https://github.com/deepch/RTSPtoWSMP4f
![RTSPtoWebRTC image](doc/demo4.png)
### Download Source
1. Download source
```bash
$ git clone https://github.com/deepch/RTSPtoWebRTC
```
3. CD to Directory
```bash
$ cd RTSPtoWebRTC/
```
4. Test Run
```bash
$ GO111MODULE=on go run *.go
```
5. Open Browser
```bash
open web browser http://127.0.0.1:8083 work chrome, safari, firefox
```
## Configuration
### Edit file config.json
format:
```bash
{
"server": {
"http_port": ":8083"
},
"streams": {
"demo1": {
"on_demand" : false
"url": "rtsp://170.93.143.139/rtplive/470011e600ef003a004ee33696235daa"
},
"demo2": {
"on_demand" : true
"url": "rtsp://admin:admin123@10.128.18.224/mpeg4"
},
"demo3": {
"on_demand" : false
"url": "rtsp://170.93.143.139/rtplive/470011e600ef003a004ee33696235daa"
}
}
}
## 配置文件说明
```
## Livestreams
Use option ``` "on_demand": false ``` otherwise you will get choppy jerky streams and performance issues when multiple clients connect.
## Limitations
Video Codecs Supported: H264
Audio Codecs Supported: pcm alaw and pcm mulaw
## Team
Deepch - https://github.com/deepch streaming developer
Dmitry - https://github.com/vdalex25 web developer
Now test work on (chrome, safari, firefox) no MAC OS
## Other Example
Examples of working with video on golang
- [RTSPtoWeb](https://github.com/deepch/RTSPtoWeb)
- [RTSPtoWebRTC](https://github.com/deepch/RTSPtoWebRTC)
- [RTSPtoWSMP4f](https://github.com/deepch/RTSPtoWSMP4f)
- [RTSPtoImage](https://github.com/deepch/RTSPtoImage)
- [RTSPtoHLS](https://github.com/deepch/RTSPtoHLS)
- [RTSPtoHLSLL](https://github.com/deepch/RTSPtoHLSLL)
[![paypal.me/AndreySemochkin](https://ionicabizau.github.io/badges/paypal.svg)](https://www.paypal.me/AndreySemochkin) - You can make one-time donations via PayPal. I'll probably buy a ~~coffee~~ tea. :tea:
# JAVA服务的地址
java_server: "127.0.0.1:8099"
# 本机的IP地址JAVA服务和本服务在一台工控机上则两个IP相同
local_ip: "127.0.0.1"
```

Binary file not shown.

@ -0,0 +1,4 @@
# JAVA服务地址
java_server: "127.0.0.1:8099"
# 本机的IP地址JAVA服务和本服务在一台工控机上则两个IP相同
local_ip: "127.0.0.1"

@ -2,25 +2,5 @@
@SET GOOS=windows
@SET GOARCH=amd64
go build -ldflags "-s -w" -o bin/rtsp2webrtc_amd64.exe
go build -ldflags "-s -w" -o RTSPtoWebRTC.exe
@SET GOOS=linux
@SET GOARCH=386
go build -ldflags "-s -w" -o bin/rtsp2webrtc_i386
@SET GOOS=linux
@SET GOARCH=amd64
go build -ldflags "-s -w" -o bin/rtsp2webrtc_amd64
@SET GOOS=linux
@SET GOARCH=arm
@SET GOARM=7
go build -ldflags "-s -w" -o bin/rtsp2webrtc_armv7
@SET GOOS=linux
@SET GOARCH=arm64
go build -ldflags "-s -w" -o bin/rtsp2webrtc_aarch64
@SET GOOS=darwin
@SET GOARCH=amd64
go build -ldflags "-s -w" -o bin/rtsp2webrtc_darwin

@ -1,18 +1,21 @@
package main
import (
"context"
"crypto/rand"
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"sync"
"time"
"github.com/deepch/vdk/codec/h264parser"
"github.com/deepch/vdk/av"
"github.com/deepch/vdk/codec/h264parser"
"gopkg.in/yaml.v2"
)
//Config global
@ -48,6 +51,17 @@ type StreamST struct {
Cl map[string]viewer
}
type HttpST struct {
JavaServer string `yaml:"java_server"`
LocalIp string `yaml:"local_ip"`
}
type HttpResST struct {
Code int `json:"code"`
Message string `json:"message"`
Data string `json:"data"`
}
type viewer struct {
c chan av.Packet
}
@ -116,9 +130,40 @@ func (element *ConfigST) GetWebRTCPortMax() uint16 {
func loadConfig() *ConfigST {
var tmp ConfigST
data, err := ioutil.ReadFile("config.json")
var httpInfo HttpST
yamlFile, err := ioutil.ReadFile("application.yml")
if err != nil {
fmt.Println(err.Error())
}
//将配置文件读取到结构体中
err = yaml.Unmarshal([]byte(yamlFile), &httpInfo)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(httpInfo)
//data, err := ioutil.ReadFile("config.json")
client := http.Client{}
request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://"+httpInfo.JavaServer+"/api/camera/rtcConfig?rtcServer="+httpInfo.LocalIp, nil)
if err != nil {
fmt.Println(err.Error())
}
resp, err := client.Do(request)
if err != nil {
fmt.Println(err)
}
bytes, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println(err.Error())
}
defer resp.Body.Close()
fmt.Println(string(bytes))
var httpRes HttpResST
err = json.Unmarshal(bytes, &httpRes)
var data = httpRes.Data
if err == nil {
err = json.Unmarshal(data, &tmp)
err = json.Unmarshal([]byte(data), &tmp)
if err != nil {
log.Fatalln(err)
}

@ -1,16 +0,0 @@
{
"server": {
"http_port": ":8083",
"ice_servers": ["stun:stun.l.google.com:19302"],
"ice_username": "",
"ice_credential": ""
},
"streams": {
"camera1": {
"on_demand": false,
"disable_audio": true,
"url": "rtsp://admin:a1234567@172.16.0.118:554/cam/realmonitor?channel=1&subtype=0"
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

@ -5,4 +5,5 @@ go 1.15
require (
github.com/deepch/vdk v0.0.0-20210508200759-5adbbcc01f89
github.com/gin-gonic/gin v1.7.0
gopkg.in/yaml.v2 v2.4.0 // indirect
)

@ -193,5 +193,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,331 +0,0 @@
/*!
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-family: sans-serif;
line-height: 1.15;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
display: block;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
text-align: left;
background-color: #fff;
}
[tabindex="-1"]:focus {
outline: 0 !important;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 0.5rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title],
abbr[data-original-title] {
text-decoration: underline;
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
border-bottom: 0;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: .5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -.25em;
}
sup {
top: -.5em;
}
a {
color: #007bff;
text-decoration: none;
background-color: transparent;
}
a:hover {
color: #0056b3;
text-decoration: underline;
}
a:not([href]):not([tabindex]) {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
color: inherit;
text-decoration: none;
}
a:not([href]):not([tabindex]):focus {
outline: 0;
}
pre,
code,
kbd,
samp {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 1em;
}
pre {
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
}
figure {
margin: 0 0 1rem;
}
img {
vertical-align: middle;
border-style: none;
}
svg {
overflow: hidden;
vertical-align: middle;
}
table {
border-collapse: collapse;
}
caption {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
color: #6c757d;
text-align: left;
caption-side: bottom;
}
th {
text-align: inherit;
}
label {
display: inline-block;
margin-bottom: 0.5rem;
}
button {
border-radius: 0;
}
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
select {
word-wrap: normal;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button:not(:disabled),
[type="button"]:not(:disabled),
[type="reset"]:not(:disabled),
[type="submit"]:not(:disabled) {
cursor: pointer;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type="radio"],
input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"] {
-webkit-appearance: listbox;
}
textarea {
overflow: auto;
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
display: block;
width: 100%;
max-width: 100%;
padding: 0;
margin-bottom: .5rem;
font-size: 1.5rem;
line-height: inherit;
color: inherit;
white-space: normal;
}
progress {
vertical-align: baseline;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
outline-offset: -2px;
-webkit-appearance: none;
}
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
summary {
display: list-item;
cursor: pointer;
}
template {
display: none;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

@ -1,8 +0,0 @@
/*!
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
/*# sourceMappingURL=bootstrap-reboot.min.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

@ -1,69 +0,0 @@
let stream = new MediaStream();
let suuid = $('#suuid').val();
let config = {
iceServers: [{
urls: ["stun:stun.l.google.com:19302"]
}]
};
const pc = new RTCPeerConnection(config);
pc.onnegotiationneeded = handleNegotiationNeededEvent;
let log = msg => {
document.getElementById('div').innerHTML += msg + '<br>'
}
pc.ontrack = function(event) {
stream.addTrack(event.track);
videoElem.srcObject = stream;
log(event.streams.length + ' track is delivered')
}
pc.oniceconnectionstatechange = e => log('here '+pc.iceConnectionState)
async function handleNegotiationNeededEvent() {
let offer = await pc.createOffer();
await pc.setLocalDescription(offer);
getRemoteSdp();
}
$(document).ready(function() {
$('#' + suuid).addClass('active');
getCodecInfo();
});
function getCodecInfo() {
$.get("../codec/" + suuid, function(data) {
try {
data = JSON.parse(data);
} catch (e) {
console.log(e);
} finally {
$.each(data,function(index,value){
pc.addTransceiver(value.Type, {
'direction': 'sendrecv'
})
})
}
});
}
let sendChannel = null;
function getRemoteSdp() {
$.post("../receiver/"+ suuid, {
suuid: suuid,
data: btoa(pc.localDescription.sdp)
}, function(data) {
try {
pc.setRemoteDescription(new RTCSessionDescription({
type: 'answer',
sdp: atob(data)
}))
} catch (e) {
console.warn(e);
}
});
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,13 +0,0 @@
<html>
<meta http-equiv="Expires" content="0">
<meta http-equiv="Last-Modified" content="0">
<meta http-equiv="Cache-Control" content="no-cache, mustrevalidate">
<meta http-equiv="Pragma" content="no-cache">
<link rel="stylesheet" href="static/css/bootstrap.min.css">
<script type="text/javascript" src="static/js/jquery-3.4.1.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>
<h2 align=center>
No Stream Found (add stream and reload page)
</h2>
</html>

@ -1,36 +0,0 @@
<html>
<meta http-equiv="Expires" content="0">
<meta http-equiv="Last-Modified" content="0">
<meta http-equiv="Cache-Control" content="no-cache, mustrevalidate">
<meta http-equiv="Pragma" content="no-cache">
<link rel="stylesheet" href="../../static/css/bootstrap.min.css">
<script type="text/javascript" src="../../static/js/jquery-3.4.1.min.js"></script>
<script src="../../static/js/bootstrap.min.js"></script>
<script src="../../static/js/adapter-latest.js"></script>
<h2 align=center>
Play Stream {{ .suuid }}
</h2>
<div class="container">
<div class="row">
<div class="col-3">
<div class="list-group">
{{ range .suuidMap }}
<a href="{{ . }}" id="{{ . }}" name="{{ . }}" class="list-group-item list-group-item-action">{{ . }}</a>
{{ end }}
</div>
</div>
<div class="col">
<input type="hidden" name="suuid" id="suuid" value="{{ .suuid }}">
<input type="hidden" name="port" id="port" value="{{ .port }}">
<input type="hidden" id="localSessionDescription" readonly="true">
<input type="hidden" id="remoteSessionDescription">
<div id="remoteVideos">
<video style="width:600px" id="videoElem" autoplay muted controls></video>
</div>
<div id="div"></div>
</div>
</div>
</div>
<script type="text/javascript" src="../../static/js/app.js?ver={{ .version }}"></script>
</html>
Loading…
Cancel
Save