Files
lkm/api.go
yangjiechina 596502d215 封装http-flv
2024-03-10 14:31:14 +08:00

99 lines
2.3 KiB
Go

package main
import (
"context"
"github.com/gorilla/mux"
"github.com/yangjiechina/avformat/utils"
"github.com/yangjiechina/live-server/flv"
"github.com/yangjiechina/live-server/stream"
"net"
"net/http"
"strings"
"time"
)
func startApiServer(addr string) {
r := mux.NewRouter()
r.HandleFunc("/live/flv/{source}", onFLV)
r.HandleFunc("/live/hls/{source}", onHLS)
http.Handle("/", r)
srv := &http.Server{
Handler: r,
Addr: addr,
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 30 * time.Second,
ReadTimeout: 30 * time.Second,
}
err := srv.ListenAndServe()
if err != nil {
panic(err)
}
}
func onFLV(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
source := vars["source"]
w.Header().Set("Content-Type", "video/x-flv")
w.Header().Set("Connection", "Keep-Alive")
w.Header().Set("Transfer-Encoding", "chunked")
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
return
}
context_ := r.Context()
w.WriteHeader(http.StatusOK)
conn, _, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
var sourceId string
if index := strings.LastIndex(source, "."); index > -1 {
sourceId = source[:index]
}
tcpAddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr)
sinkId := stream.GenerateSinkId(tcpAddr)
sink := flv.NewFLVSink(sinkId, sourceId, conn)
go func(ctx context.Context) {
sink.(*stream.SinkImpl).Play(sink, func() {
//sink.(*stream.SinkImpl).PlayDone(sink, nil, nil)
}, func(state utils.HookState) {
conn.Close()
})
}(context_)
}
func onHLS(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
source := vars["source"]
w.Header().Set("Content-Type", "application/vnd.apple.mpegurl")
//删除末尾的.ts/.m3u8, 请确保id中不存在.
//var sourceId string
//if index := strings.LastIndex(source, "."); index > -1 {
// sourceId = source[:index]
//}
//
//tcpAddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr)
//sinkId := stream.GenerateSinkId(tcpAddr)
if strings.HasSuffix(source, ".m3u8") {
//查询是否存在hls流, 不存在-等生成后再响应m3u8文件. 存在-直接响应m3u8文件
http.ServeFile(w, r, "../tmp/"+source)
} else if strings.HasSuffix(source, ".ts") {
http.ServeFile(w, r, "../tmp/"+source)
}
}