mirror of
https://github.com/cnotch/ipchub.git
synced 2025-09-26 19:41:18 +08:00
113 lines
2.6 KiB
Go
Executable File
113 lines
2.6 KiB
Go
Executable File
// Copyright (c) 2019,CAOHONGJU All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package hls
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/cnotch/ipchub/config"
|
|
"github.com/cnotch/ipchub/media"
|
|
"github.com/cnotch/xlog"
|
|
)
|
|
|
|
// GetM3u8 .
|
|
func GetM3u8(logger *xlog.Logger, path string, token string, addr string, w http.ResponseWriter) {
|
|
// 需要手动启动,如果需要转换或拉流,很耗时
|
|
var c media.Hlsable
|
|
s := media.GetOrCreate(path)
|
|
if s != nil {
|
|
c = s.Hlsable()
|
|
}
|
|
|
|
if c == nil {
|
|
logger.Errorf("http-hls: not found stream '%s'", path)
|
|
http.Error(w, "404 page not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
var err error
|
|
var cont []byte
|
|
|
|
// 最多等待完成 30 秒
|
|
waitSeconds := int(1.5 * float64(3*config.HlsFragment()))
|
|
for i := 0; i < waitSeconds; i++ {
|
|
cont, err = c.M3u8(token)
|
|
if err == nil {
|
|
break
|
|
}
|
|
|
|
<-time.After(time.Second)
|
|
}
|
|
|
|
if err != nil {
|
|
logger.Errorf("http-hls: request playlist error, %v.", err)
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
w.Header().Set("Cache-Control", "no-cache")
|
|
w.Header().Set("Content-Type", "application/x-mpegURL")
|
|
w.Header().Set("Content-Length", strconv.Itoa(len(cont)))
|
|
w.Write(cont)
|
|
|
|
if logger.LevelEnabled(xlog.DebugLevel) {
|
|
logger.Debugf("m3u8 ===>>>\r\n%s", string(cont))
|
|
}
|
|
}
|
|
|
|
// GetTS .
|
|
func GetTS(logger *xlog.Logger, path string, addr string, w http.ResponseWriter) {
|
|
i := strings.LastIndex(path, "/")
|
|
if i < 0 {
|
|
logger.Errorf("http-hls: path illegal `%s`", path)
|
|
http.Error(w, "Path illegal", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
streamPath := path[:i]
|
|
seqStr := path[i+1:]
|
|
seq, err := strconv.Atoi(seqStr)
|
|
if err != nil {
|
|
logger.Errorf("http-hls: path illegal `%s`", path)
|
|
http.Error(w, "Path illegal", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// 查找的消费者但不创建
|
|
var c media.Hlsable
|
|
s := media.GetOrCreate(streamPath)
|
|
if s != nil {
|
|
c = s.Hlsable()
|
|
}
|
|
|
|
if c == nil {
|
|
logger.Errorf("http-hls: not found `%s`", path)
|
|
http.Error(w, "404 page not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
reader, size, err := c.Segment(seq)
|
|
if err != nil {
|
|
logger.Errorf("http-hls: not found `%s`", path)
|
|
http.Error(w, "404 page not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
defer func() {
|
|
if closer, ok := reader.(io.Closer); ok {
|
|
closer.Close()
|
|
}
|
|
}()
|
|
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
w.Header().Set("Content-Type", "video/mp2ts")
|
|
w.Header().Set("Content-Length", strconv.Itoa(size))
|
|
io.Copy(w, reader)
|
|
}
|