live video streaming server in golang
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

178 lines
3.7 KiB

package main
import (
"crypto/tls"
"fmt"
"net"
"path"
"runtime"
"time"
"github.com/gwuhaolin/livego/configure"
"github.com/gwuhaolin/livego/protocol/api"
"github.com/gwuhaolin/livego/protocol/hls"
"github.com/gwuhaolin/livego/protocol/httpflv"
"github.com/gwuhaolin/livego/protocol/rtmp"
log "github.com/sirupsen/logrus"
)
var VERSION = "master"
func startHls() *hls.Server {
hlsAddr := configure.Config.GetString("hls_addr")
hlsListen, err := net.Listen("tcp", hlsAddr)
if err != nil {
log.Fatal(err)
}
hlsServer := hls.NewServer()
go func() {
defer func() {
if r := recover(); r != nil {
log.Error("HLS server panic: ", r)
}
}()
log.Info("HLS listen On ", hlsAddr)
hlsServer.Serve(hlsListen)
}()
return hlsServer
}
func startRtmp(stream *rtmp.RtmpStream, hlsServer *hls.Server) {
rtmpAddr := configure.Config.GetString("rtmp_addr")
isRtmps := configure.Config.GetBool("enable_rtmps")
var rtmpListen net.Listener
if isRtmps {
certPath := configure.Config.GetString("rtmps_cert")
keyPath := configure.Config.GetString("rtmps_key")
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil {
log.Fatal(err)
}
rtmpListen, err = tls.Listen("tcp", rtmpAddr, &tls.Config{
Certificates: []tls.Certificate{cert},
})
if err != nil {
log.Fatal(err)
}
} else {
var err error
rtmpListen, err = net.Listen("tcp", rtmpAddr)
if err != nil {
log.Fatal(err)
}
}
var rtmpServer *rtmp.Server
if hlsServer == nil {
rtmpServer = rtmp.NewRtmpServer(stream, nil)
log.Info("HLS server disable....")
} else {
rtmpServer = rtmp.NewRtmpServer(stream, hlsServer)
log.Info("HLS server enable....")
}
defer func() {
if r := recover(); r != nil {
log.Error("RTMP server panic: ", r)
}
}()
if isRtmps {
log.Info("RTMPS Listen On ", rtmpAddr)
} else {
log.Info("RTMP Listen On ", rtmpAddr)
}
rtmpServer.Serve(rtmpListen)
}
func startHTTPFlv(stream *rtmp.RtmpStream) {
httpflvAddr := configure.Config.GetString("httpflv_addr")
flvListen, err := net.Listen("tcp", httpflvAddr)
if err != nil {
log.Fatal(err)
}
hdlServer := httpflv.NewServer(stream)
go func() {
defer func() {
if r := recover(); r != nil {
log.Error("HTTP-FLV server panic: ", r)
}
}()
log.Info("HTTP-FLV listen On ", httpflvAddr)
hdlServer.Serve(flvListen)
}()
}
func startAPI(stream *rtmp.RtmpStream) {
apiAddr := configure.Config.GetString("api_addr")
rtmpAddr := configure.Config.GetString("rtmp_addr")
if apiAddr != "" {
opListen, err := net.Listen("tcp", apiAddr)
if err != nil {
log.Fatal(err)
}
opServer := api.NewServer(stream, rtmpAddr)
go func() {
defer func() {
if r := recover(); r != nil {
log.Error("HTTP-API server panic: ", r)
}
}()
log.Info("HTTP-API listen On ", apiAddr)
opServer.Serve(opListen)
}()
}
}
func init() {
log.SetFormatter(&log.TextFormatter{
FullTimestamp: true,
CallerPrettyfier: func(f *runtime.Frame) (string, string) {
filename := path.Base(f.File)
return fmt.Sprintf("%s()", f.Function), fmt.Sprintf(" %s:%d", filename, f.Line)
},
})
}
func main() {
defer func() {
if r := recover(); r != nil {
log.Error("livego panic: ", r)
time.Sleep(1 * time.Second)
}
}()
log.Infof(`
_ _ ____
| | (_)_ _____ / ___| ___
| | | \ \ / / _ \ | _ / _ \
| |___| |\ V / __/ |_| | (_) |
|_____|_| \_/ \___|\____|\___/
version: %s
`, VERSION)
apps := configure.Applications{}
configure.Config.UnmarshalKey("server", &apps)
for _, app := range apps {
stream := rtmp.NewRtmpStream()
var hlsServer *hls.Server
if app.Hls {
hlsServer = startHls()
}
if app.Flv {
startHTTPFlv(stream)
}
if app.Api {
startAPI(stream)
}
startRtmp(stream, hlsServer)
}
}