support off the record mp4, mkv (#10)

This commit is contained in:
Han Gyoung-Su
2024-09-13 08:27:29 +09:00
committed by GitHub
parent 2f4e79ab78
commit c3255d6a20
10 changed files with 93 additions and 21 deletions

View File

@@ -72,6 +72,7 @@ Start streaming by choosing from the following broadcast options:
- **HLS:**
- URL: `http://127.0.0.1:8044/hls/test/master.m3u8`
- Viewer: `http://127.0.0.1:8044/m3u8player.html?streamid=test`
- **WHEP:**
- URL: `http://127.0.0.1:8044/`

View File

@@ -6,3 +6,7 @@ llhls = false
disk_ram = true
[docker]
mode = false
[mp4]
record=false
[ebml]
record=false

View File

@@ -5,6 +5,8 @@ type Config struct {
RTMP RTMP `mapstructure:"rtmp"`
Service Service `mapstructure:"service"`
Docker DockerConfig `mapstructure:"docker"`
MP4 MP4 `mapstructure:"mp4"`
EBML EBML `mapstructure:"ebml"`
}
type RTMP struct {
@@ -20,3 +22,11 @@ type Service struct {
type DockerConfig struct {
Mode bool `mapstructure:"mode"`
}
type MP4 struct {
Record bool `mapstructure:"record"`
}
type EBML struct {
Record bool `mapstructure:"record"`
}

4
go.mod
View File

@@ -4,6 +4,7 @@ go 1.21
require (
github.com/asticode/go-astiav v0.19.0
github.com/asticode/go-astits v1.13.0
github.com/at-wat/ebml-go v0.17.1
github.com/bluenviron/gohlslib v1.4.0
github.com/deepch/vdk v0.0.27
@@ -25,12 +26,12 @@ require (
require (
github.com/abema/go-mp4 v1.2.0 // indirect
github.com/asticode/go-astikit v0.43.0 // indirect
github.com/asticode/go-astits v1.13.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bluenviron/mediacommon v1.11.1-0.20240525122142-20163863aa75 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@@ -77,6 +78,7 @@ require (
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

4
go.sum
View File

@@ -30,6 +30,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -248,6 +250,8 @@ golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=

43
main.go
View File

@@ -10,11 +10,11 @@ import (
"liveflow/media/streamer/egress/whep"
"liveflow/media/streamer/ingress/whip"
"net/http"
_ "net/http/pprof" // pprof을 사용하기 위한 패키지
"strconv"
_ "net/http/pprof" // pprof을 사용하기 위한 패키지
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/pion/webrtc/v3"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/sirupsen/logrus"
@@ -63,11 +63,16 @@ func main() {
api.HideBanner = true
hlsHub := hlshub.NewHLSHub()
hlsHandler := httpsrv.NewHandler(hlsHub)
hlsRoute := api.Group("/hls", middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"*"}, // Adjust origins as necessary
AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodOptions},
}))
api.GET("/prometheus", echo.WrapHandler(promhttp.Handler()))
api.GET("/debug/pprof/*", echo.WrapHandler(http.DefaultServeMux))
api.GET("/hls/:streamID/master.m3u8", hlsHandler.HandleMasterM3U8)
api.GET("/hls/:streamID/:playlistName/stream.m3u8", hlsHandler.HandleM3U8)
api.GET("/hls/:streamID/:playlistName/:resourceName", hlsHandler.HandleM3U8)
// Enable CORS only for /hls routes
hlsRoute.GET("/:streamID/master.m3u8", hlsHandler.HandleMasterM3U8)
hlsRoute.GET("/:streamID/:playlistName/stream.m3u8", hlsHandler.HandleM3U8)
hlsRoute.GET("/:streamID/:playlistName/:resourceName", hlsHandler.HandleM3U8)
whipServer := whip.NewWHIP(whip.WHIPArgs{
Hub: hub,
Tracks: tracks,
@@ -82,19 +87,23 @@ func main() {
// ingress 의 rtmp, whip 서비스로부터 streamID를 받아 Service, ContainerMP4, WHEP 서비스 시작
for source := range hub.SubscribeToStreamID() {
log.Infof(ctx, "New streamID received: %s", source.StreamID())
mp4 := mp4.NewMP4(mp4.MP4Args{
Hub: hub,
})
err = mp4.Start(ctx, source)
if err != nil {
log.Errorf(ctx, "failed to start mp4: %v", err)
if conf.MP4.Record {
mp4 := mp4.NewMP4(mp4.MP4Args{
Hub: hub,
})
err = mp4.Start(ctx, source)
if err != nil {
log.Errorf(ctx, "failed to start mp4: %v", err)
}
}
webmStarter := webm.NewWEBM(webm.WebMArgs{
Hub: hub,
})
err = webmStarter.Start(ctx, source)
if err != nil {
log.Errorf(ctx, "failed to start webm: %v", err)
if conf.EBML.Record {
webmStarter := webm.NewWEBM(webm.WebMArgs{
Hub: hub,
})
err = webmStarter.Start(ctx, source)
if err != nil {
log.Errorf(ctx, "failed to start webm: %v", err)
}
}
hls := hls.NewHLS(hls.HLSArgs{
Hub: hub,

View File

@@ -70,7 +70,8 @@ func (h *HLS) Start(ctx context.Context, source hub.Source) error {
fields.SourceName: source.Name(),
})
log.Info(ctx, "start hls")
log.Info(ctx, "view url: ", fmt.Sprintf("http://127.0.0.1:%d/hls/%s/master.m3u8", h.port, source.StreamID()))
log.Info(ctx, "view url: ",
fmt.Sprintf("http://localhost:8044/m3u8player.html?streamid=%s", source.StreamID()))
sub := h.hub.Subscribe(source.StreamID())
go func() {

View File

@@ -56,7 +56,7 @@ func NewWHIP(args WHIPArgs) *WHIP {
func (r *WHIP) RegisterRoute() {
whipServer := r.echo
whipServer.Static("/", ".")
whipServer.Static("/", "static")
whipServer.POST("/whip", r.whipHandler)
whipServer.POST("/whep", r.whepHandler)
}

41
static/m3u8player.html Normal file
View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/npm/@mux/mux-video@0"></script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>M3U8 Player</title>
</head>
<body>
<div id="root"></div>
<mux-video
id="hls-player"
prefer-playback="mse"
controls
autoplay
muted
>
</mux-video>
<script>
// Function to get the query parameters from the URL
function getQueryParam(param) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(param);
}
// Get streamid from the URL query parameters
const streamId = getQueryParam('streamid');
if (streamId) {
// Update the src dynamically
const host = window.location.protocol + '//' + window.location.host;
const player = document.getElementById('hls-player');
player.src = `${host}/hls/${streamId}/master.m3u8`;
} else {
console.error('Stream ID not provided in the URL');
}
</script>
</body>
</html>