mirror of
https://github.com/lkmio/lkm.git
synced 2025-09-27 03:26:01 +08:00
99 lines
2.3 KiB
Go
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)
|
|
}
|
|
|
|
}
|