mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
add media to capture config.
This commit is contained in:
parent
21140d3dd3
commit
6b14e01415
@ -122,7 +122,7 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
|
|||||||
videoIDs: config.VideoIDs,
|
videoIDs: config.VideoIDs,
|
||||||
|
|
||||||
// sources
|
// sources
|
||||||
webcam: streamSrcNew(map[string]string{
|
webcam: streamSrcNew(config.WebcamEnabled, map[string]string{
|
||||||
codec.VP8().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
codec.VP8().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
||||||
fmt.Sprintf("! application/x-rtp, payload=%d, encoding-name=VP8-DRAFT-IETF-01 ", codec.VP8().PayloadType) +
|
fmt.Sprintf("! application/x-rtp, payload=%d, encoding-name=VP8-DRAFT-IETF-01 ", codec.VP8().PayloadType) +
|
||||||
"! rtpvp8depay " +
|
"! rtpvp8depay " +
|
||||||
@ -130,7 +130,8 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
|
|||||||
"! videoconvert " +
|
"! videoconvert " +
|
||||||
"! videorate " +
|
"! videorate " +
|
||||||
"! identity drop-allocation=true " +
|
"! identity drop-allocation=true " +
|
||||||
"! v4l2sink sync=false device=/dev/video0",
|
fmt.Sprintf("! v4l2sink sync=false device=%s", config.WebcamDevice),
|
||||||
|
// TODO: Test this pipeline.
|
||||||
codec.VP9().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
codec.VP9().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
||||||
"! application/x-rtp " +
|
"! application/x-rtp " +
|
||||||
"! rtpvp9depay " +
|
"! rtpvp9depay " +
|
||||||
@ -138,7 +139,8 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
|
|||||||
"! videoconvert " +
|
"! videoconvert " +
|
||||||
"! videorate " +
|
"! videorate " +
|
||||||
"! identity drop-allocation=true " +
|
"! identity drop-allocation=true " +
|
||||||
"! v4l2sink sync=false device=/dev/video0",
|
fmt.Sprintf("! v4l2sink sync=false device=%s", config.WebcamDevice),
|
||||||
|
// TODO: Test this pipeline.
|
||||||
codec.H264().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
codec.H264().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
||||||
"! application/x-rtp " +
|
"! application/x-rtp " +
|
||||||
"! rtph264depay " +
|
"! rtph264depay " +
|
||||||
@ -146,19 +148,20 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
|
|||||||
"! videoconvert " +
|
"! videoconvert " +
|
||||||
"! videorate " +
|
"! videorate " +
|
||||||
"! identity drop-allocation=true " +
|
"! identity drop-allocation=true " +
|
||||||
"! v4l2sink sync=false device=/dev/video0",
|
fmt.Sprintf("! v4l2sink sync=false device=%s", config.WebcamDevice),
|
||||||
}, "webcam"),
|
}, "webcam"),
|
||||||
microphone: streamSrcNew(map[string]string{
|
microphone: streamSrcNew(config.MicrophoneEnabled, map[string]string{
|
||||||
codec.Opus().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
codec.Opus().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
||||||
fmt.Sprintf("! application/x-rtp, payload=%d, encoding-name=OPUS ", codec.Opus().PayloadType) +
|
fmt.Sprintf("! application/x-rtp, payload=%d, encoding-name=OPUS ", codec.Opus().PayloadType) +
|
||||||
"! rtpopusdepay " +
|
"! rtpopusdepay " +
|
||||||
"! decodebin " +
|
"! decodebin " +
|
||||||
"! pulsesink device=audio_input",
|
fmt.Sprintf("! pulsesink device=%s", config.MicrophoneDevice),
|
||||||
|
// TODO: Test this pipeline.
|
||||||
codec.G722().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
codec.G722().Name: "appsrc format=time is-live=true do-timestamp=true name=appsrc " +
|
||||||
"! application/x-rtp clock-rate=8000 " +
|
"! application/x-rtp clock-rate=8000 " +
|
||||||
"! rtpg722depay " +
|
"! rtpg722depay " +
|
||||||
"! decodebin " +
|
"! decodebin " +
|
||||||
"! pulsesink device=audio_input",
|
fmt.Sprintf("! pulsesink device=%s", config.MicrophoneDevice),
|
||||||
}, "microphone"),
|
}, "microphone"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ func (manager *ScreencastManagerCtx) start() error {
|
|||||||
defer manager.mu.Unlock()
|
defer manager.mu.Unlock()
|
||||||
|
|
||||||
if !manager.enabled {
|
if !manager.enabled {
|
||||||
return errors.New("screenshot pipeline not enabled")
|
return errors.New("screencast not enabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := manager.createPipeline()
|
err := manager.createPipeline()
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
type StreamSrcManagerCtx struct {
|
type StreamSrcManagerCtx struct {
|
||||||
logger zerolog.Logger
|
logger zerolog.Logger
|
||||||
|
enabled bool
|
||||||
codecPipeline map[string]string // codec -> pipeline
|
codecPipeline map[string]string // codec -> pipeline
|
||||||
|
|
||||||
codec codec.RTPCodec
|
codec codec.RTPCodec
|
||||||
@ -22,7 +23,7 @@ type StreamSrcManagerCtx struct {
|
|||||||
pipelineStr string
|
pipelineStr string
|
||||||
}
|
}
|
||||||
|
|
||||||
func streamSrcNew(codecPipeline map[string]string, video_id string) *StreamSrcManagerCtx {
|
func streamSrcNew(enabled bool, codecPipeline map[string]string, video_id string) *StreamSrcManagerCtx {
|
||||||
logger := log.With().
|
logger := log.With().
|
||||||
Str("module", "capture").
|
Str("module", "capture").
|
||||||
Str("submodule", "stream-src").
|
Str("submodule", "stream-src").
|
||||||
@ -30,6 +31,7 @@ func streamSrcNew(codecPipeline map[string]string, video_id string) *StreamSrcMa
|
|||||||
|
|
||||||
return &StreamSrcManagerCtx{
|
return &StreamSrcManagerCtx{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
enabled: enabled,
|
||||||
codecPipeline: codecPipeline,
|
codecPipeline: codecPipeline,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,6 +54,10 @@ func (manager *StreamSrcManagerCtx) Start(codec codec.RTPCodec) error {
|
|||||||
return types.ErrCapturePipelineAlreadyExists
|
return types.ErrCapturePipelineAlreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !manager.enabled {
|
||||||
|
return errors.New("stream-src not enabled")
|
||||||
|
}
|
||||||
|
|
||||||
found := false
|
found := false
|
||||||
for codecName, pipeline := range manager.codecPipeline {
|
for codecName, pipeline := range manager.codecPipeline {
|
||||||
if codecName == codec.Name {
|
if codecName == codec.Name {
|
||||||
|
@ -33,11 +33,17 @@ type Capture struct {
|
|||||||
ScreencastRate string
|
ScreencastRate string
|
||||||
ScreencastQuality string
|
ScreencastQuality string
|
||||||
ScreencastPipeline string
|
ScreencastPipeline string
|
||||||
|
|
||||||
|
WebcamEnabled bool
|
||||||
|
WebcamDevice string
|
||||||
|
|
||||||
|
MicrophoneEnabled bool
|
||||||
|
MicrophoneDevice string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Capture) Init(cmd *cobra.Command) error {
|
func (Capture) Init(cmd *cobra.Command) error {
|
||||||
// audio
|
// audio
|
||||||
cmd.PersistentFlags().String("capture.audio.device", "audio_output.monitor", "audio device to capture")
|
cmd.PersistentFlags().String("capture.audio.device", "audio_output.monitor", "pulseaudio device to capture")
|
||||||
if err := viper.BindPFlag("capture.audio.device", cmd.PersistentFlags().Lookup("capture.audio.device")); err != nil {
|
if err := viper.BindPFlag("capture.audio.device", cmd.PersistentFlags().Lookup("capture.audio.device")); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -110,6 +116,28 @@ func (Capture) Init(cmd *cobra.Command) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// webcam
|
||||||
|
cmd.PersistentFlags().Bool("capture.webcam.enabled", false, "enable webcam stream")
|
||||||
|
if err := viper.BindPFlag("capture.webcam.enabled", cmd.PersistentFlags().Lookup("capture.webcam.enabled")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.PersistentFlags().String("capture.webcam.device", "/dev/video0", "v4l2sink device used for webcam")
|
||||||
|
if err := viper.BindPFlag("capture.webcam.device", cmd.PersistentFlags().Lookup("capture.webcam.device")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// microphone
|
||||||
|
cmd.PersistentFlags().Bool("capture.microphone.enabled", true, "enable microphone stream")
|
||||||
|
if err := viper.BindPFlag("capture.microphone.enabled", cmd.PersistentFlags().Lookup("capture.microphone.enabled")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.PersistentFlags().String("capture.microphone.device", "audio_input", "pulseaudio device used for microphone")
|
||||||
|
if err := viper.BindPFlag("capture.microphone.device", cmd.PersistentFlags().Lookup("capture.microphone.device")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,4 +202,12 @@ func (s *Capture) Set() {
|
|||||||
s.ScreencastRate = viper.GetString("capture.screencast.rate")
|
s.ScreencastRate = viper.GetString("capture.screencast.rate")
|
||||||
s.ScreencastQuality = viper.GetString("capture.screencast.quality")
|
s.ScreencastQuality = viper.GetString("capture.screencast.quality")
|
||||||
s.ScreencastPipeline = viper.GetString("capture.screencast.pipeline")
|
s.ScreencastPipeline = viper.GetString("capture.screencast.pipeline")
|
||||||
|
|
||||||
|
// webcam
|
||||||
|
s.WebcamEnabled = viper.GetBool("capture.webcam.enabled")
|
||||||
|
s.WebcamDevice = viper.GetString("capture.webcam.device")
|
||||||
|
|
||||||
|
// microphone
|
||||||
|
s.MicrophoneEnabled = viper.GetBool("capture.microphone.enabled")
|
||||||
|
s.MicrophoneDevice = viper.GetString("capture.microphone.device")
|
||||||
}
|
}
|
||||||
|
@ -157,24 +157,24 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, videoID strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
connection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
connection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
|
||||||
if !session.Profile().CanShareMedia {
|
defer receiver.Stop()
|
||||||
logger.Warn().
|
|
||||||
Str("kind", track.Kind().String()).
|
|
||||||
Msgf("got track but share media is disabled for this session")
|
|
||||||
|
|
||||||
receiver.Stop()
|
logger := logger.With().
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Info().
|
|
||||||
Str("kind", track.Kind().String()).
|
Str("kind", track.Kind().String()).
|
||||||
Str("mime", track.Codec().RTPCodecCapability.MimeType).
|
Str("mime", track.Codec().RTPCodecCapability.MimeType).
|
||||||
Msgf("received new track")
|
Logger()
|
||||||
|
|
||||||
|
logger.Info().Msgf("received new track")
|
||||||
|
|
||||||
|
if !session.Profile().CanShareMedia {
|
||||||
|
logger.Warn().Msg("share media is disabled for this session")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// parse codec
|
// parse codec
|
||||||
codec, ok := codec.ParseRTC(track.Codec())
|
codec, ok := codec.ParseRTC(track.Codec())
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Warn().Str("mime", track.Codec().RTPCodecCapability.MimeType).Msg("unknown codec")
|
logger.Warn().Msg("unknown codec")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,6 +192,7 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, videoID strin
|
|||||||
logger.Err(err).Msg("failed to start pipeline")
|
logger.Err(err).Msg("failed to start pipeline")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer srcManager.Stop()
|
||||||
|
|
||||||
// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
|
// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
|
||||||
ticker := time.NewTicker(time.Second * 3)
|
ticker := time.NewTicker(time.Second * 3)
|
||||||
@ -199,9 +200,9 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, videoID strin
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
rtcpSendErr := connection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}})
|
err := connection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}})
|
||||||
if rtcpSendErr != nil {
|
if err != nil {
|
||||||
fmt.Println(rtcpSendErr)
|
logger.Err(err).Msg("rtcp send err")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -210,16 +211,14 @@ func (manager *WebRTCManagerCtx) CreatePeer(session types.Session, videoID strin
|
|||||||
for {
|
for {
|
||||||
i, _, err := track.Read(buf)
|
i, _, err := track.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Err(err).Msg("failed read from pipeline")
|
logger.Warn().Err(err).Msg("failed read from track")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
srcManager.Push(buf[:i])
|
srcManager.Push(buf[:i])
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Warn().Msg("src manager stream connection died, stopping")
|
logger.Info().Msg("track data finished")
|
||||||
srcManager.Stop()
|
|
||||||
logger.Warn().Msg("src manager stream stopped!!!!!!!!!!!!!!!")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
connection.OnDataChannel(func(dc *webrtc.DataChannel) {
|
connection.OnDataChannel(func(dc *webrtc.DataChannel) {
|
||||||
|
Loading…
Reference in New Issue
Block a user