Skip to content

Commit

Permalink
init project
Browse files Browse the repository at this point in the history
  • Loading branch information
wanghaoxi3000 committed Dec 16, 2019
1 parent 9640436 commit e19e6cc
Show file tree
Hide file tree
Showing 18 changed files with 696 additions and 0 deletions.
49 changes: 49 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
FROM ubuntu:18.04 as builder

ENV APP_DIR=/go/src
ENV GO_VERSION=1.13.3
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.io

COPY . ${APP_DIR}

RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list \
&& sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list \
&& apt-get update && apt-get install -y wget make g++ \
&& wget -nv https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz && tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz

WORKDIR ${APP_DIR}
RUN export PATH=$PATH:/usr/local/go/bin && make all


FROM ubuntu:18.04

ENV TZ=Asia/Shanghai
ENV LANG=en_US.UTF-8

RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list \
&& sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list \
&& apt-get update \
&& ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime && echo ${TZ} > /etc/timezone \
&& apt-get install -y locales tzdata ffmpeg \
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 \
&& apt-get clean && apt-get autoclean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

ENV APP_DIR=/usr/local/hkapi
ENV GIN_MODE=release
ENV LOG_LEVEL=info
ENV NVR_SAVE_PATH=/srv/hkapi/stream
ENV SQLITE_PATH=/var/hkapi/database
ENV DB_TYPE=sqlite3
ENV DB_DSN=${SQLITE_PATH}/sqlite.db

COPY --from=builder /go/src/lib ${APP_DIR}/lib
COPY --from=builder /go/src/hkapi.out ${APP_DIR}
COPY --from=builder /go/src/run.sh ${APP_DIR}

EXPOSE 3000

WORKDIR ${APP_DIR}
RUN mkdir -p ${NVR_SAVE_PATH} && mkdir -p ${SQLITE_PATH} && chmod +x run.sh

ENTRYPOINT [ "./run.sh" ]
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# gin-rtsp

## 参考
[JSMpeg – MPEG1 Video & MP2 Audio Decoder in JavaScript](https://github.com/phoboslab/jsmpeg/)
5 changes: 5 additions & 0 deletions RtspWebSocket/jsmpeg.min.js

Large diffs are not rendered by default.

Binary file added RtspWebSocket/video-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions RtspWebSocket/view-stream.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<title>JSMpeg Stream Client</title>
<style type="text/css">
html, body {
text-align: center;
}
</style>

</head>
<body>
<canvas id="video-canvas"></canvas>

<canvas id="video-canvas1"></canvas>

<script type="text/javascript" src="jsmpeg.min.js"></script>
<script type="text/javascript">
var canvas = document.getElementById('video-canvas');
var url = 'ws://127.0.0.1:3000/stream/live/5b96bff4-bdb2-3edb-9d6e-f96eda03da56';
var player = new JSMpeg.Player(url, {canvas: canvas});


var canvas1 = document.getElementById('video-canvas1');
var url1 = 'ws://127.0.0.1:3000/stream/live/5b96bff4-bdb2-3edb-9d6e-f96eda03da56';
var player1 = new JSMpeg.Player(url1, {canvas: canvas1});

</script>
</body>
</html>
36 changes: 36 additions & 0 deletions api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package api

import (
"encoding/json"
"fmt"
"ginrtsp/serializer"

"github.com/gin-gonic/gin"
"gopkg.in/go-playground/validator.v8"
)

// errorRequest 请求数据错误处理
func errorRequest(err error) *serializer.Response {
if ve, ok := err.(validator.ValidationErrors); ok {
for _, e := range ve {
return serializer.Err(
400,
fmt.Sprintf("%s %s", e.Field, e.Tag),
err,
)
}
}
if _, ok := err.(*json.UnmarshalTypeError); ok {
return serializer.Err(400, "JSON类型不匹配", err)
}

return serializer.Err(400, "参数错误", err)
}

// Ping 状态检查
func Ping(c *gin.Context) {
c.JSON(200, serializer.Response{
Code: 0,
Msg: "Pong",
})
}
39 changes: 39 additions & 0 deletions api/rtsp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package api

import (
"bufio"
"ginrtsp/service"

"github.com/gin-gonic/gin"
)

// PlayRTSP 启动 FFMPEG 播放 RTSP 流
func PlayRTSP(c *gin.Context) {
srv := &service.RTSPTransSrv{}
if err := c.ShouldBind(srv); err != nil {
c.JSON(400, errorRequest(err))
return
}

ret := srv.Service()
c.JSON(ret.Code, ret)
}

// Mpeg1Video 接收 mpeg1vido 数据流
func Mpeg1Video(c *gin.Context) {
bodyReader := bufio.NewReader(c.Request.Body)

for {
data, err := bodyReader.ReadBytes('\n')
if err != nil {
break
}

service.WsManager.GroupBoardcast(c.Param("channel"), data)
}
}

// Wsplay 通过 websocket 播放 mpegts 数据
func Wsplay(c *gin.Context) {
service.WsManager.RegisterClient(c)
}
20 changes: 20 additions & 0 deletions conf/conf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package conf

import (
"ginrtsp/util"
"os"

"github.com/joho/godotenv"
)

// Init 初始化配置项
func Init() {
// 从本地读取环境变量
godotenv.Load()

if os.Getenv("GIN_MODE") == "release" {
util.BuildLogger("info")
} else {
util.BuildLogger("debug")
}
}
11 changes: 11 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module ginrtsp

go 1.13

require (
github.com/gin-gonic/gin v1.5.0
github.com/gorilla/websocket v1.4.1
github.com/joho/godotenv v1.3.0
github.com/satori/go.uuid v1.2.0
gopkg.in/go-playground/validator.v8 v8.18.2
)
52 changes: 52 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc=
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Binary file added main
Binary file not shown.
18 changes: 18 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"ginrtsp/conf"
"ginrtsp/server"
"ginrtsp/service"
)

func main() {
// 从配置文件读取配置, 初始化各个模块
conf.Init()

// 装载路由
r := server.NewRouter()

go service.WsManager.Start()
r.Run(":3000")
}
16 changes: 16 additions & 0 deletions serializer/rtsptrans.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package serializer

// RTSPPlayPath RTSP play 信息序列化器
type RTSPPlayPath struct {
Path string `json:"path"`
}

// BuildRTSPPlayPathResponse 序列化 RTSP play 响应
func BuildRTSPPlayPathResponse(path string) *Response {
return &Response{
Data: &RTSPPlayPath{
Path: path,
},
Msg: "success",
}
}
32 changes: 32 additions & 0 deletions serializer/serializer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package serializer

import (
"ginrtsp/util"

"github.com/gin-gonic/gin"
)

// Response 基础序列化器
type Response struct {
Code int `json:"code"`
Data interface{} `json:"data,omitempty"`
Msg string `json:"msg"`
Error string `json:"error,omitempty"`
}

// Err 通用错误处理
func Err(errCode int, msg string, err error) *Response {
res := Response{
Code: errCode,
Msg: msg,
}

if err != nil {
util.Log().Error(err.Error())
// 生产环境隐藏底层报错
if gin.Mode() != gin.ReleaseMode {
res.Error = err.Error()
}
}
return &res
}
23 changes: 23 additions & 0 deletions server/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package server

import (
"ginrtsp/api"

"github.com/gin-gonic/gin"
)

// NewRouter Gin 路由配置
func NewRouter() *gin.Engine {
r := gin.Default()

// 路由
r.GET("/ping", api.Ping)
route := r.Group("/stream")
{
route.POST("/play", api.PlayRTSP)
route.POST("/upload/:channel", api.Mpeg1Video)
route.GET("/live/:channel", api.Wsplay)
}

return r
}
Loading

0 comments on commit e19e6cc

Please sign in to comment.