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.
EasyDarwin/routers/streams.go

208 lines
5.4 KiB

6 years ago
package routers
import (
"bytes"
"fmt"
"log"
"math"
"net/http"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"github.com/EasyDarwin/EasyDarwin/rtsp"
"github.com/gin-gonic/gin"
"github.com/penggy/EasyGoLib/utils"
6 years ago
)
func (h *APIHandler) StreamStart(c *gin.Context) {
type Form struct {
URL string `form:"url" binding:"required"`
CustomPath string `form:"customPath"`
IdleTimeout int `form:"idleTimeout"`
HeartbeatInterval int `form:"heartbeatInterval"`
6 years ago
}
var form Form
err := c.Bind(&form)
if err != nil {
log.Printf("Pull to push err:%v", err)
6 years ago
return
}
client, err := rtsp.NewRTSPClient(rtsp.GetServer(), form.URL, int64(form.HeartbeatInterval)*1000)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, err.Error())
return
}
if form.CustomPath != "" && !strings.HasPrefix(form.CustomPath, "/") {
form.CustomPath = "/" + form.CustomPath
}
client.CustomPath = form.CustomPath
6 years ago
pusher := rtsp.NewClientPusher(client)
if rtsp.GetServer().GetPusher(pusher.Path()) != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, fmt.Sprintf("Path %s already exists", client.Path))
return
}
err = client.Start(time.Duration(form.IdleTimeout) * time.Second)
if err != nil {
log.Printf("Pull stream err :%v", err)
c.AbortWithStatusJSON(http.StatusBadRequest, fmt.Sprintf("Pull stream err: %v", err))
return
}
log.Printf("Pull to push %v success ", form)
6 years ago
rtsp.GetServer().AddPusher(pusher)
c.IndentedJSON(200, pusher.ID())
6 years ago
}
func (h *APIHandler) StreamStop(c *gin.Context) {
type Form struct {
ID string `form:"id" binding:"required"`
}
var form Form
err := c.Bind(&form)
if err != nil {
log.Printf("stop pull to push err:%v", err)
return
}
pushers := rtsp.GetServer().GetPushers()
for _, v := range pushers {
if v.ID() == form.ID {
v.Stop()
c.IndentedJSON(200, "OK")
log.Printf("Stop %v success ", v)
return
}
}
c.AbortWithStatusJSON(http.StatusBadRequest, fmt.Sprintf("Pusher[%s] not found", form.ID))
}
func (h *APIHandler) RecordFolders(c *gin.Context) {
mp4Path := utils.Conf().Section("rtsp").Key("mp4_dir_path").MustString("")
form := utils.NewPageForm()
if err := c.Bind(form); err != nil {
log.Printf("record folder bind err:%v", err)
return
}
var files = make([]interface{}, 0)
if mp4Path != "" {
visit := func(files *[]interface{}) filepath.WalkFunc {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == mp4Path {
return nil
}
if !info.IsDir() {
return nil
}
*files = append(*files, map[string]interface{}{"folder": info.Name()})
return filepath.SkipDir
}
}
err := filepath.Walk(mp4Path, visit(&files))
if err != nil {
log.Printf("Query RecordFolders err:%v", err)
}
}
pr := utils.NewPageResult(files)
if form.Sort != "" {
pr.Sort(form.Sort, form.Order)
}
pr.Slice(form.Start, form.Limit)
c.IndentedJSON(200, pr)
}
func (h *APIHandler) RecordFiles(c *gin.Context) {
type Form struct {
utils.PageForm
Folder string `form:"folder" binding:"required"`
StartAt int `form:"beginUTCSecond"`
StopAt int `form:"endUTCSecond"`
}
var form = Form{}
form.Limit = math.MaxUint32
err := c.Bind(&form)
if err != nil {
log.Printf("record file bind err:%v", err)
return
}
files := make([]interface{}, 0)
mp4Path := utils.Conf().Section("rtsp").Key("mp4_dir_path").MustString("")
if mp4Path != "" {
ffmpeg_path := utils.Conf().Section("rtsp").Key("ffmpeg_path").MustString("")
ffmpeg_folder, executable := filepath.Split(ffmpeg_path)
split := strings.Split(executable, ".")
suffix := ""
if len(split) > 1 {
suffix = split[1]
}
ffprobe := ffmpeg_folder + "ffprobe" + suffix
folder := filepath.Join(mp4Path, form.Folder)
visit := func(files *[]interface{}) filepath.WalkFunc {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == folder {
return nil
}
if info.IsDir() {
return nil
}
if info.Size() == 0 {
return nil
}
if info.Name() == ".DS_Store" {
return nil
}
cmd := exec.Command(ffprobe, "-i", path)
cmdOutput := &bytes.Buffer{}
//cmd.Stdout = cmdOutput
cmd.Stderr = cmdOutput
err = cmd.Run()
bytes := cmdOutput.Bytes()
output := string(bytes)
//log.Printf("%v result:%v", cmd, output)
var average = regexp.MustCompile(`Duration: ((\d+):(\d+):(\d+).(\d+))`)
result := average.FindStringSubmatch(output)
duration := time.Duration(0)
durationStr := ""
if len(result) > 0 {
durationStr = result[1]
h, _ := strconv.Atoi(result[2])
duration += time.Duration(h) * time.Hour
m, _ := strconv.Atoi(result[3])
duration += time.Duration(m) * time.Minute
s, _ := strconv.Atoi(result[4])
duration += time.Duration(s) * time.Second
millis, _ := strconv.Atoi(result[5])
duration += time.Duration(millis) * time.Millisecond
}
*files = append(*files, map[string]interface{}{
"name": info.Name(),
"durationMillis": duration / time.Millisecond,
"duration": durationStr})
return nil
}
}
err = filepath.Walk(folder, visit(&files))
if err != nil {
log.Printf("Query RecordFolders err:%v", err)
}
}
pr := utils.NewPageResult(files)
if form.Sort != "" {
pr.Sort(form.Sort, form.Order)
}
pr.Slice(form.Start, form.Limit)
c.IndentedJSON(200, pr)
6 years ago
}