From 3407d9b3dde330d2f9ef6cd4f3b532bc493bf0eb Mon Sep 17 00:00:00 2001 From: notch Date: Mon, 28 Dec 2020 14:46:52 +0800 Subject: [PATCH] update docs --- README.md | 34 +++++++++++++++------------------- docs/apis.md | 30 +++++++++++------------------- docs/quickstart.md | 26 +++++++++----------------- provider/auth/json.go | 5 ++++- service/apis.go | 21 ++++++++++----------- stats/conns.go | 1 - 6 files changed, 49 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 5113b3a..7bb2d01 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,29 @@ # ipchub -一个小而美的流媒体服务器,即拷即用。 +一个即拷即用、支持摄像头集中管理、多级路由及h5播放的流媒体服务器,。 +## 项目背景 偶尔和前同事聊天,说到一些小的监控项目需要把IP摄像头集中管理,并提供html播放能力。闲来无事就试着开发一个打发时间,也作为学习 go 语言的一个实践。 在此之前没有流媒体经验,没有go语言项目开发经验。看了一些文档,参考了一些开源项目,主要包括: + [emitter](https://github.com/emitter-io/emitter) 学习多协议共享端口等网络编程技能 + [EasyDarwin](https://github.com/EasyDarwin/EasyDarwin) 为加深对rtsp协议的理解 -+ [seal](https://github.com/calabashdad/seal.git) rtmp/flv 相关协议学习及 hls 相关处理 ++ [seal](https://github.com/calabashdad/seal.git) rtmp/flv hls 服务的理解 -## 做什么 -摄像头集中、多级路由及h5播放 -功能: -+ 流媒体源支持 - + RTSP拉流 - + RTSP推流 -+ 流媒体消费支持 - + RTSP流 - + RTSP WEBSOCKET 代理 +## 主要特性 + ++ 基于纯 Golang 开发 ++ 支持 Windows、Linux、macOS 平台 ++ 支持 RTSP 推流(主动推送) ++ 支持 RTSP 拉流(拉取摄像头或其他流媒体服务器资源) ++ 支持 H264+AAC H5播放,包括: + HTTP-FLV - + WEBSOCKET-FLV + + Websocket-FLV + HTTP-HLS -+ 流媒体多级路由 -+ 用户流媒体推拉权限管理 -+ 业务系统集成API - -## 不做什么 -+ 不存储 -+ 不转码 + + Websocket-RTSP(实验): 实时性更好 ++ 支持级联部署服务器,自动拉取流 ++ 支持流媒体推拉的用户权限管理 ++ 业务系统集成 RestfulAPI ## 文档 + [Quick Start](/docs/quickstart.md) diff --git a/docs/apis.md b/docs/apis.md index 13301d6..16b535b 100755 --- a/docs/apis.md +++ b/docs/apis.md @@ -1,5 +1,6 @@ ## 1 系统API -系统API无需登录,可以匿名访问 +系统API无需登录,可以匿名访问。 + ### 1.1 服务器信息查询 GET /api/v1/server #### 1.1.1 参数和响应 @@ -23,7 +24,7 @@ duration | string | 持续时间 | #### 1.1.2 示例 curl 示例: ``` shell -curl http://locahost:1554/api/v1/server +curl http://localhost:1554/api/v1/server ``` 响应: @@ -31,7 +32,7 @@ curl http://locahost:1554/api/v1/server { "vendor": "CAOHONGJU", "name": "ipchub", - "version": "V0.8.0", + "version": "V1.0", "os": "Darwin", "arch": "AMD64", "start_on": "2019-07-15T14:02:16.638804+08:00", @@ -64,15 +65,12 @@ streams | object | 流信息 | streams.sc| number | 流媒体源数量 | streams.cc|number|流媒体消费者数量 | rtsp| object| RTSP连接信息 | -rtsp.total|number|总链接数 | -rtsp.active | number | 活跃连接数 | -wsp| object| WSP连接信息 | -wsp.total|number|总链接数 | -wsp.active | number | 活跃连接数 | +rtsp.total|number|累计总链接数 | +rtsp.active | number | 当前活跃连接数 | flv| object| flv连接信息 | -flv.total|number|总链接数 | -flv.active | number | 活跃连接数 | -extra | object | 额外信息 | +flv.total|number|累计总链接数 | +flv.active | number | 当前活跃连接数 | +extra | object | 运行时内存等信息 | #### 1.2.1 示例 curl 示例一: @@ -97,10 +95,6 @@ curl http://localhost:1554/api/v1/runtime "total": 0, "active": 0 }, - "wsp": { - "total": 0, - "active": 0 - }, "flv": { "total": 0, "active": 0 @@ -215,10 +209,8 @@ http://.../api/v1/streams/rtsp/room/door?token=your_access_token http://.../streams/room/door.flv?token=your_access_token + websocket-flv ws://.../ws/room/door.flv?token=your_access_token -+ wps -ws://.../ws/room/door?token=your_access_token -+ rtmp -rtmp://.../room/door?token=your_access_token ++ http-flv +http://.../steams/room/door.m3u8?token=your_access_token ### 1.4 刷新access token GET api/v1/refreshtoken?token={refresh_tokebn} diff --git a/docs/quickstart.md b/docs/quickstart.md index 8cb5aef..6b4494a 100755 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -21,18 +21,14 @@ ] ``` 我们配置了两个路由: -+ /group/door ++ /group/door : 集团大门直接连接到摄像头 ++ /hr/ : 人力资源部门的摄像头路由到下级的服务器 + 假设下级服务器有 /door/video1 和 /door/video2 两个摄像头,那么你可以通过 .../hr/door/video1 和 .../hr/door/video2 访问它们。 -集团大门直接连接到摄像头 -+ /hr/ - -人力资源部门的摄像头路由到下级的服务器中;hr的服务器包含:/door/video1和/door/video2 - -## 3. 使用 +## 3. 访问流媒体 服务器提供了多种访问终端摄像头的方式,包括: + rtsp + websocket-rtsp -+ wsp(websocket 代理模式) + http-flv + websocket-flv + http-hls @@ -57,20 +53,16 @@ rtsp://localhost:1554/hr/door/video1 请求在服务器内自动变成去拉取r 打开demo地址:http://localhost:1554/demos/rtsp 输入:ws://localhost:1554/ws/group/door 即可访问 -### 3.3 使用wsp访问 -和上面一样,打开demo地址:http://localhost:1554/demos/wsp -输入:rtsp://localhost:1554/group/door 即可访问 - -### 3.4 使用http-flv访问 +### 3.3 使用http-flv访问 打开demo地址:http://localhost:1554/demos/flv 输入:http://locaolhost:1554/streams/group/door.flv 即可访问 由于 Chrome 对长连接的流限制为6个,因此如果使用 Chrome 打开更多建议使用websocket-flv -### 3.5 使用 websocket-flv访问 +### 3.4 使用 websocket-flv访问 打开demo地址:http://localhost:1554/demos/flv 输入:ws://locaolhost:1554/ws/group/door.flv 即可访问 -### 3.6 使用 http-hls访问 +### 3.5 使用 http-hls访问 由于 iOS的Safari不支持上述任何http访问模式,请使用 http-hls 在浏览器输入: http://localhost:1554/streams/group/door.m3m8 即可访问 **注意:** 由于http-hls的段文件默认被放在内存中,占用大量的内存;如系统内存不足,请配置存储路径。 @@ -81,10 +73,10 @@ rtsp://localhost:1554/hr/door/video1 请求在服务器内自动变成去拉取r 输入:http://locaolhost:1554/streams/group/door.flv?token=7f97509e321a18ccf281607f4c0bd4fb 其中 token 通过登录api获得 -对于配置用户,参考配置和Api文档 +相关信息请参考[配置文档](config.md) 和 [Api 文档](apis.md) ## 5. 浏览器支持情况 -wsp、http-flv、websocket-flv等浏览器访问,支持: +http-flv、websocket-flv等浏览器访问,支持: + Firefox v.42+ + Chrome v.23+ + OSX Safari v.8+ diff --git a/provider/auth/json.go b/provider/auth/json.go index 9198518..c2a22ea 100755 --- a/provider/auth/json.go +++ b/provider/auth/json.go @@ -53,7 +53,10 @@ func (p *jsonProvider) LoadAll() ([]*User, error) { path := p.filePath if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { - return nil, nil + return []*User{{ + Name: "admin", + Password: "admin", + Admin: true}}, nil } return nil, err } diff --git a/service/apis.go b/service/apis.go index 399e60d..8d580ab 100755 --- a/service/apis.go +++ b/service/apis.go @@ -122,15 +122,16 @@ func (s *Service) onLogin(w http.ResponseWriter, r *http.Request, pathParams api // 提取凭证 var uc UserCredentials - err := json.NewDecoder(r.Body).Decode(&uc) - if err != nil { - // 尝试 Form解析 - uc.Username = r.FormValue("username") - uc.Password = r.FormValue("password") - if len(uc.Username) == 0 || len(uc.Password) == 0 { - http.Error(w, "用户名或密码错误", http.StatusForbidden) - return - } + + if err := json.NewDecoder(r.Body).Decode(&uc); err != nil { + http.Error(w, "未提供用户名或密码", http.StatusForbidden) + return + } + + // 尝试 Form解析 + if len(uc.Username) == 0 || len(uc.Password) == 0 { + http.Error(w, "用户名或密码错误", http.StatusForbidden) + return } // 验证用户和密码 @@ -187,7 +188,6 @@ func (s *Service) onGetRuntime(w http.ResponseWriter, r *http.Request, pathParam Proc stats.Proc `json:"proc"` Streams sccc `json:"streams"` Rtsp stats.ConnsSample `json:"rtsp"` - Wsp stats.ConnsSample `json:"wsp"` Flv stats.ConnsSample `json:"flv"` Extra *stats.Runtime `json:"extra,omitempty"` } @@ -198,7 +198,6 @@ func (s *Service) onGetRuntime(w http.ResponseWriter, r *http.Request, pathParam Proc: stats.MeasureRuntime(), Streams: sccc{sc, cc}, Rtsp: stats.RtspConns.GetSample(), - Wsp: stats.WspConns.GetSample(), Flv: stats.FlvConns.GetSample(), } diff --git a/stats/conns.go b/stats/conns.go index cbc1a8c..0f79084 100755 --- a/stats/conns.go +++ b/stats/conns.go @@ -11,7 +11,6 @@ import ( // 全局变量 var ( RtspConns = NewConns() // RTSP连接统计 - WspConns = NewConns() // WSP连接统计 FlvConns = NewConns() // flv连接统计 )