This commit is contained in:
parent
8960cbae5f
commit
4d0ce87f09
2
go.mod
2
go.mod
|
@ -9,7 +9,7 @@ require (
|
|||
github.com/abema/go-mp4 v1.2.0
|
||||
github.com/alecthomas/kong v1.2.1
|
||||
github.com/asticode/go-astits v1.13.0
|
||||
github.com/bluenviron/gohlslib v1.4.0
|
||||
github.com/bluenviron/gohlslib/v2 v2.0.0-20241003172246-076f27fbe0f8
|
||||
github.com/bluenviron/gortsplib/v4 v4.10.6
|
||||
github.com/bluenviron/mediacommon v1.12.4
|
||||
github.com/datarhei/gosrt v0.7.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -20,8 +20,8 @@ github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwf
|
|||
github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
|
||||
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c h1:8XZeJrs4+ZYhJeJ2aZxADI2tGADS15AzIF8MQ8XAhT4=
|
||||
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c/go.mod h1:x1vxHcL/9AVzuk5HOloOEPrtJY0MaalYr78afXZ+pWI=
|
||||
github.com/bluenviron/gohlslib v1.4.0 h1:3a9W1x8eqlxJUKt1sJCunPGtti5ALIY2ik4GU0RVe7E=
|
||||
github.com/bluenviron/gohlslib v1.4.0/go.mod h1:q5ZElzNw5GRbV1VEI45qkcPbKBco6BP58QEY5HyFsmo=
|
||||
github.com/bluenviron/gohlslib/v2 v2.0.0-20241003172246-076f27fbe0f8 h1:OQeYfxJg5otVKa33HWJ63E+IxCJ5Ty0qwCBPD2JcIso=
|
||||
github.com/bluenviron/gohlslib/v2 v2.0.0-20241003172246-076f27fbe0f8/go.mod h1:DVvQIj+MjYydWuYDCgP+s0/GplDgUSpDNXCA/BVLhu4=
|
||||
github.com/bluenviron/gortsplib/v4 v4.10.6 h1:KMvVcU21xxQQu1Jqn6D/z/FoIMn+QEKE1dBDWt4aWvg=
|
||||
github.com/bluenviron/gortsplib/v4 v4.10.6/go.mod h1:/7C8qoGEsIQupuVw8YnXANpqBMNBpZ+51xFreLGiN2g=
|
||||
github.com/bluenviron/mediacommon v1.12.4 h1:7VrA/W/iDB7VELquXqRjgjzUSJT3llZYgXjFN9WkByo=
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gohlslib"
|
||||
"github.com/bluenviron/gohlslib/v2"
|
||||
"github.com/bluenviron/gortsplib/v4"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/auth"
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/bluenviron/gohlslib"
|
||||
"github.com/bluenviron/gohlslib/v2"
|
||||
)
|
||||
|
||||
// HLSVariant is the hlsVariant parameter.
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/bluenviron/gohlslib"
|
||||
"github.com/bluenviron/gohlslib/pkg/codecs"
|
||||
"github.com/bluenviron/gohlslib/v2"
|
||||
"github.com/bluenviron/gohlslib/v2/pkg/codecs"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
||||
"github.com/bluenviron/mediamtx/internal/asyncwriter"
|
||||
"github.com/bluenviron/mediamtx/internal/logger"
|
||||
|
@ -22,11 +22,18 @@ func setupVideoTrack(
|
|||
stream *stream.Stream,
|
||||
writer *asyncwriter.Writer,
|
||||
muxer *gohlslib.Muxer,
|
||||
) format.Format {
|
||||
setuppedFormats map[format.Format]struct{},
|
||||
) {
|
||||
var videoFormatAV1 *format.AV1
|
||||
videoMedia := stream.Desc().FindFormat(&videoFormatAV1)
|
||||
|
||||
if videoFormatAV1 != nil {
|
||||
track := &gohlslib.Track{
|
||||
Codec: &codecs.AV1{},
|
||||
}
|
||||
muxer.Tracks = append(muxer.Tracks, track)
|
||||
setuppedFormats[videoFormatAV1] = struct{}{}
|
||||
|
||||
stream.AddReader(writer, videoMedia, videoFormatAV1, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.AV1)
|
||||
|
||||
|
@ -34,7 +41,7 @@ func setupVideoTrack(
|
|||
return nil
|
||||
}
|
||||
|
||||
err := muxer.WriteAV1(tunit.NTP, tunit.PTS, tunit.TU)
|
||||
err := muxer.WriteAV1(track, tunit.NTP, tunit.PTS, tunit.TU)
|
||||
if err != nil {
|
||||
return fmt.Errorf("muxer error: %w", err)
|
||||
}
|
||||
|
@ -42,16 +49,19 @@ func setupVideoTrack(
|
|||
return nil
|
||||
})
|
||||
|
||||
muxer.VideoTrack = &gohlslib.Track{
|
||||
Codec: &codecs.AV1{},
|
||||
}
|
||||
return videoFormatAV1
|
||||
return
|
||||
}
|
||||
|
||||
var videoFormatVP9 *format.VP9
|
||||
videoMedia = stream.Desc().FindFormat(&videoFormatVP9)
|
||||
|
||||
if videoFormatVP9 != nil {
|
||||
track := &gohlslib.Track{
|
||||
Codec: &codecs.VP9{},
|
||||
}
|
||||
muxer.Tracks = append(muxer.Tracks, track)
|
||||
setuppedFormats[videoFormatVP9] = struct{}{}
|
||||
|
||||
stream.AddReader(writer, videoMedia, videoFormatVP9, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.VP9)
|
||||
|
||||
|
@ -59,7 +69,7 @@ func setupVideoTrack(
|
|||
return nil
|
||||
}
|
||||
|
||||
err := muxer.WriteVP9(tunit.NTP, tunit.PTS, tunit.Frame)
|
||||
err := muxer.WriteVP9(track, tunit.NTP, tunit.PTS, tunit.Frame)
|
||||
if err != nil {
|
||||
return fmt.Errorf("muxer error: %w", err)
|
||||
}
|
||||
|
@ -67,16 +77,24 @@ func setupVideoTrack(
|
|||
return nil
|
||||
})
|
||||
|
||||
muxer.VideoTrack = &gohlslib.Track{
|
||||
Codec: &codecs.VP9{},
|
||||
}
|
||||
return videoFormatVP9
|
||||
return
|
||||
}
|
||||
|
||||
var videoFormatH265 *format.H265
|
||||
videoMedia = stream.Desc().FindFormat(&videoFormatH265)
|
||||
|
||||
if videoFormatH265 != nil {
|
||||
vps, sps, pps := videoFormatH265.SafeParams()
|
||||
track := &gohlslib.Track{
|
||||
Codec: &codecs.H265{
|
||||
VPS: vps,
|
||||
SPS: sps,
|
||||
PPS: pps,
|
||||
},
|
||||
}
|
||||
muxer.Tracks = append(muxer.Tracks, track)
|
||||
setuppedFormats[videoFormatH265] = struct{}{}
|
||||
|
||||
stream.AddReader(writer, videoMedia, videoFormatH265, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.H265)
|
||||
|
||||
|
@ -84,7 +102,7 @@ func setupVideoTrack(
|
|||
return nil
|
||||
}
|
||||
|
||||
err := muxer.WriteH265(tunit.NTP, tunit.PTS, tunit.AU)
|
||||
err := muxer.WriteH265(track, tunit.NTP, tunit.PTS, tunit.AU)
|
||||
if err != nil {
|
||||
return fmt.Errorf("muxer error: %w", err)
|
||||
}
|
||||
|
@ -92,22 +110,23 @@ func setupVideoTrack(
|
|||
return nil
|
||||
})
|
||||
|
||||
vps, sps, pps := videoFormatH265.SafeParams()
|
||||
|
||||
muxer.VideoTrack = &gohlslib.Track{
|
||||
Codec: &codecs.H265{
|
||||
VPS: vps,
|
||||
SPS: sps,
|
||||
PPS: pps,
|
||||
},
|
||||
}
|
||||
return videoFormatH265
|
||||
return
|
||||
}
|
||||
|
||||
var videoFormatH264 *format.H264
|
||||
videoMedia = stream.Desc().FindFormat(&videoFormatH264)
|
||||
|
||||
if videoFormatH264 != nil {
|
||||
sps, pps := videoFormatH264.SafeParams()
|
||||
track := &gohlslib.Track{
|
||||
Codec: &codecs.H264{
|
||||
SPS: sps,
|
||||
PPS: pps,
|
||||
},
|
||||
}
|
||||
muxer.Tracks = append(muxer.Tracks, track)
|
||||
setuppedFormats[videoFormatH264] = struct{}{}
|
||||
|
||||
stream.AddReader(writer, videoMedia, videoFormatH264, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.H264)
|
||||
|
||||
|
@ -115,7 +134,7 @@ func setupVideoTrack(
|
|||
return nil
|
||||
}
|
||||
|
||||
err := muxer.WriteH264(tunit.NTP, tunit.PTS, tunit.AU)
|
||||
err := muxer.WriteH264(track, tunit.NTP, tunit.PTS, tunit.AU)
|
||||
if err != nil {
|
||||
return fmt.Errorf("muxer error: %w", err)
|
||||
}
|
||||
|
@ -123,85 +142,76 @@ func setupVideoTrack(
|
|||
return nil
|
||||
})
|
||||
|
||||
sps, pps := videoFormatH264.SafeParams()
|
||||
|
||||
muxer.VideoTrack = &gohlslib.Track{
|
||||
Codec: &codecs.H264{
|
||||
SPS: sps,
|
||||
PPS: pps,
|
||||
},
|
||||
}
|
||||
return videoFormatH264
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupAudioTrack(
|
||||
func setupAudioTracks(
|
||||
stream *stream.Stream,
|
||||
writer *asyncwriter.Writer,
|
||||
muxer *gohlslib.Muxer,
|
||||
) format.Format {
|
||||
var audioFormatOpus *format.Opus
|
||||
audioMedia := stream.Desc().FindFormat(&audioFormatOpus)
|
||||
setuppedFormats map[format.Format]struct{},
|
||||
) {
|
||||
for _, media := range stream.Desc().Medias {
|
||||
for _, forma := range media.Formats {
|
||||
switch forma := forma.(type) {
|
||||
case *format.Opus:
|
||||
track := &gohlslib.Track{
|
||||
Codec: &codecs.Opus{
|
||||
ChannelCount: forma.ChannelCount,
|
||||
},
|
||||
}
|
||||
muxer.Tracks = append(muxer.Tracks, track)
|
||||
setuppedFormats[forma] = struct{}{}
|
||||
|
||||
if audioFormatOpus != nil {
|
||||
stream.AddReader(writer, audioMedia, audioFormatOpus, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.Opus)
|
||||
stream.AddReader(writer, media, forma, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.Opus)
|
||||
|
||||
err := muxer.WriteOpus(
|
||||
tunit.NTP,
|
||||
tunit.PTS,
|
||||
tunit.Packets)
|
||||
if err != nil {
|
||||
return fmt.Errorf("muxer error: %w", err)
|
||||
}
|
||||
err := muxer.WriteOpus(
|
||||
track,
|
||||
tunit.NTP,
|
||||
tunit.PTS,
|
||||
tunit.Packets)
|
||||
if err != nil {
|
||||
return fmt.Errorf("muxer error: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
muxer.AudioTrack = &gohlslib.Track{
|
||||
Codec: &codecs.Opus{
|
||||
ChannelCount: audioFormatOpus.ChannelCount,
|
||||
},
|
||||
}
|
||||
return audioFormatOpus
|
||||
}
|
||||
|
||||
var audioFormatMPEG4Audio *format.MPEG4Audio
|
||||
audioMedia = stream.Desc().FindFormat(&audioFormatMPEG4Audio)
|
||||
|
||||
if audioFormatMPEG4Audio != nil {
|
||||
co := audioFormatMPEG4Audio.GetConfig()
|
||||
if co != nil {
|
||||
stream.AddReader(writer, audioMedia, audioFormatMPEG4Audio, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.MPEG4Audio)
|
||||
|
||||
if tunit.AUs == nil {
|
||||
return nil
|
||||
})
|
||||
|
||||
case *format.MPEG4Audio:
|
||||
co := forma.GetConfig()
|
||||
if co != nil {
|
||||
track := &gohlslib.Track{
|
||||
Codec: &codecs.MPEG4Audio{
|
||||
Config: *co,
|
||||
},
|
||||
}
|
||||
muxer.Tracks = append(muxer.Tracks, track)
|
||||
setuppedFormats[forma] = struct{}{}
|
||||
|
||||
stream.AddReader(writer, media, forma, func(u unit.Unit) error {
|
||||
tunit := u.(*unit.MPEG4Audio)
|
||||
|
||||
if tunit.AUs == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := muxer.WriteMPEG4Audio(
|
||||
track,
|
||||
tunit.NTP,
|
||||
tunit.PTS,
|
||||
tunit.AUs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("muxer error: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
err := muxer.WriteMPEG4Audio(
|
||||
tunit.NTP,
|
||||
tunit.PTS,
|
||||
tunit.AUs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("muxer error: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
muxer.AudioTrack = &gohlslib.Track{
|
||||
Codec: &codecs.MPEG4Audio{
|
||||
Config: *co,
|
||||
},
|
||||
}
|
||||
return audioFormatMPEG4Audio
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FromStream maps a MediaMTX stream to a HLS muxer.
|
||||
|
@ -211,26 +221,30 @@ func FromStream(
|
|||
muxer *gohlslib.Muxer,
|
||||
l logger.Writer,
|
||||
) error {
|
||||
videoFormat := setupVideoTrack(
|
||||
setuppedFormats := make(map[format.Format]struct{})
|
||||
|
||||
setupVideoTrack(
|
||||
stream,
|
||||
writer,
|
||||
muxer,
|
||||
setuppedFormats,
|
||||
)
|
||||
|
||||
audioFormat := setupAudioTrack(
|
||||
setupAudioTracks(
|
||||
stream,
|
||||
writer,
|
||||
muxer,
|
||||
setuppedFormats,
|
||||
)
|
||||
|
||||
if videoFormat == nil && audioFormat == nil {
|
||||
if len(muxer.Tracks) == 0 {
|
||||
return ErrNoSupportedCodecs
|
||||
}
|
||||
|
||||
n := 1
|
||||
for _, media := range stream.Desc().Medias {
|
||||
for _, forma := range media.Formats {
|
||||
if forma != videoFormat && forma != audioFormat {
|
||||
if _, ok := setuppedFormats[forma]; !ok {
|
||||
l.Log(logger.Warn, "skipping track %d (%s)", n, forma.Codec())
|
||||
}
|
||||
n++
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/bluenviron/gohlslib"
|
||||
"github.com/bluenviron/gohlslib/v2"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
||||
"github.com/bluenviron/mediamtx/internal/asyncwriter"
|
||||
|
@ -32,7 +32,9 @@ func TestFromStreamNoSupportedCodecs(t *testing.T) {
|
|||
t.Error("should not happen")
|
||||
})
|
||||
|
||||
err = FromStream(stream, writer, nil, l)
|
||||
m := &gohlslib.Muxer{}
|
||||
|
||||
err = FromStream(stream, writer, m, l)
|
||||
require.Equal(t, ErrNoSupportedCodecs, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ package hls
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gohlslib"
|
||||
"github.com/bluenviron/gohlslib/pkg/codecs"
|
||||
"github.com/bluenviron/gohlslib/v2"
|
||||
"github.com/bluenviron/gohlslib/v2/pkg/codecs"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
||||
"github.com/bluenviron/mediamtx/internal/stream"
|
||||
|
|
|
@ -3,7 +3,7 @@ package hls
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/bluenviron/gohlslib"
|
||||
"github.com/bluenviron/gohlslib/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
|
@ -36,12 +36,41 @@ html, body {
|
|||
box-sizing: border-box;
|
||||
text-shadow: 0 0 5px black;
|
||||
}
|
||||
#lang-icon {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0iI2ZmZiIgeG1sbnM6dj0iaHR0cHM6Ly92ZWN0YS5pby9uYW5vIj48cGF0aCBkPSJNMzguNSAzMy45bC0xLjktMS42YzIuNS0yLjkgMy44LTYuMyAzLjgtOS45IDAtMy4xLTEtNi4xLTIuOS04LjhsMi4xLTEuNWMyLjIgMy4xIDMuNCA2LjYgMy40IDEwLjItLjEgNC4zLTEuNiA4LjMtNC41IDExLjZ6TTUuNiAyMy4yaC0zYy0uNSAwLTEgLjUtMSAxLjF2MTAuNWMwIC42LjQgMS4xIDEgMS4xaDNjLjIgMCAuMyAwIC40LjFsMTMuOCA3LjhjLjYuNCAxLjQtLjIgMS40LTFWMTYuM2MwLS44LS44LTEuMy0xLjQtMUw2LjEgMjMuMWMtLjIuMS0uMy4xLS41LjF6bTIxLTE2LjlMMTIuOCAxNGMtLjEuMS0uMy4xLS40LjFoLTNjLS41IDAtMSAuNS0xIDEuMVYyMGwxMi4yLTYuOGExLjM2IDEuMzYgMCAwIDEgMS41IDBjLjUuMy44LjguOCAxLjV2MTcuOWwzLjcgMi4xYy42LjQgMS40LS4yIDEuNC0xVjcuMmMuMS0uOC0uNy0xLjMtMS40LS45em0xNi41IDMwLjJsLTEuOS0xLjZjMy4xLTMuNyA0LjctOCA0LjctMTIuNSAwLTQtMS4zLTcuOC0zLjctMTEuMmwyLjEtMS41YzIuNyAzLjggNC4yIDguMiA0LjIgMTIuNy0uMiA1LjEtMiA5LjktNS40IDE0LjF6TTM1IDMxLjFsLTItMS42YzEuNy0yLjEgMi42LTQuNiAyLjYtNy4yIDAtMi40LS44LTQuNy0yLjItNi43bDItMS41YzEuOCAyLjUgMi43IDUuMyAyLjcgOC4yIDAgMy4yLTEuMSA2LjItMy4xIDguOHoiLz48L3N2Zz4=");
|
||||
background-size: 80%;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
cursor: pointer;
|
||||
}
|
||||
#lang-list {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
background: rgb(190, 190, 190);
|
||||
color: black;
|
||||
}
|
||||
#lang-icon:hover #lang-list {
|
||||
display: block;
|
||||
}
|
||||
#lang-list div {
|
||||
border-bottom: 1px solid black;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<video id="video"></video>
|
||||
<div id="message"></div>
|
||||
<div id="lang-icon"><div id="lang-list"></div></div>
|
||||
|
||||
<script src="hls.min.js"></script>
|
||||
|
||||
|
@ -51,6 +80,8 @@ const retryPause = 2000;
|
|||
|
||||
const video = document.getElementById('video');
|
||||
const message = document.getElementById('message');
|
||||
const langIcon = document.getElementById('lang-icon');
|
||||
const langList = document.getElementById('lang-list');
|
||||
|
||||
let defaultControls = false;
|
||||
|
||||
|
@ -83,8 +114,11 @@ const loadStream = () => {
|
|||
if (data.fatal) {
|
||||
hls.destroy();
|
||||
|
||||
langIcon.style.display = 'none';
|
||||
langList.innerHTML = '';
|
||||
|
||||
if (data.details === 'manifestIncompatibleCodecsError') {
|
||||
setMessage('stream makes use of codecs which are incompatible with this browser or operative system');
|
||||
setMessage('stream makes use of codecs which are not compatible with this browser or operative system');
|
||||
} else if (data.response && data.response.code === 404) {
|
||||
setMessage('stream not found, retrying in some seconds');
|
||||
} else {
|
||||
|
@ -99,7 +133,19 @@ const loadStream = () => {
|
|||
hls.loadSource('index.m3u8' + window.location.search);
|
||||
});
|
||||
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||
hls.on(Hls.Events.MANIFEST_LOADED, () => {
|
||||
if (hls.audioTracks.length > 1) {
|
||||
for (const track of hls.audioTracks) {
|
||||
const div = document.createElement('DIV');
|
||||
div.innerText = track.name;
|
||||
div.addEventListener('click', () => {
|
||||
hls.audioTrack = track.id;
|
||||
});
|
||||
langList.appendChild(div);
|
||||
}
|
||||
langIcon.style.display = 'block';
|
||||
}
|
||||
|
||||
setMessage('');
|
||||
video.play();
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gohlslib"
|
||||
"github.com/bluenviron/gohlslib/v2"
|
||||
"github.com/bluenviron/mediamtx/internal/asyncwriter"
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
"github.com/bluenviron/mediamtx/internal/defs"
|
||||
|
@ -42,12 +42,15 @@ func (mi *muxerInstance) initialize() error {
|
|||
}
|
||||
|
||||
mi.hmuxer = &gohlslib.Muxer{
|
||||
Variant: gohlslib.MuxerVariant(mi.variant),
|
||||
SegmentCount: mi.segmentCount,
|
||||
SegmentDuration: time.Duration(mi.segmentDuration),
|
||||
PartDuration: time.Duration(mi.partDuration),
|
||||
SegmentMaxSize: uint64(mi.segmentMaxSize),
|
||||
Directory: muxerDirectory,
|
||||
Variant: gohlslib.MuxerVariant(mi.variant),
|
||||
SegmentCount: mi.segmentCount,
|
||||
SegmentMinDuration: time.Duration(mi.segmentDuration),
|
||||
PartMinDuration: time.Duration(mi.partDuration),
|
||||
SegmentMaxSize: uint64(mi.segmentMaxSize),
|
||||
Directory: muxerDirectory,
|
||||
OnEncodeError: func(err error) {
|
||||
mi.Log(logger.Warn, err.Error())
|
||||
},
|
||||
}
|
||||
|
||||
err := hls.FromStream(mi.stream, mi.writer, mi.hmuxer, mi)
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gohlslib"
|
||||
"github.com/bluenviron/gohlslib/pkg/codecs"
|
||||
"github.com/bluenviron/gohlslib/v2"
|
||||
"github.com/bluenviron/gohlslib/v2/pkg/codecs"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
"github.com/bluenviron/mediamtx/internal/defs"
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/bluenviron/gohlslib"
|
||||
"github.com/bluenviron/gohlslib/v2"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
|
|
Loading…
Reference in New Issue