refactor: use io.Pipe and ffmpeg's stdin (#1148)

This removes the usage of `syscall.Mkfifo` which was previously used and
won't work on Windows systems and opens the door for other processes on
the computer to interfere in the rtmp stream (dumping bad content in the
fifo, removing the file, blocking the file in offline status).
Instead, this patch introduces an `io.Pipe` which pipes the RTMP stream
to the ffmpeg command while staying in Owncast.

Further links:
* ffmpeg on using `pipe:0` as an input: https://ffmpeg.org/ffmpeg-protocols.html#pipe
This commit is contained in:
Jannik
2021-07-03 21:28:25 +02:00
committed by GitHub
parent 0858e2ed52
commit 3f9f4a151c
4 changed files with 23 additions and 29 deletions

View File

@ -4,8 +4,6 @@ import (
"fmt"
"io"
"net"
"os"
"syscall"
"time"
"github.com/nareix/joy5/format/flv"
@ -15,21 +13,20 @@ import (
"github.com/nareix/joy5/format/rtmp"
"github.com/owncast/owncast/core/data"
"github.com/owncast/owncast/models"
"github.com/owncast/owncast/utils"
)
var (
_hasInboundRTMPConnection = false
)
var _pipe *os.File
var _pipe *io.PipeWriter
var _rtmpConnection net.Conn
var _setStreamAsConnected func()
var _setStreamAsConnected func(*io.PipeReader)
var _setBroadcaster func(models.Broadcaster)
// Start starts the rtmp service, listening on specified RTMP port.
func Start(setStreamAsConnected func(), setBroadcaster func(models.Broadcaster)) {
func Start(setStreamAsConnected func(*io.PipeReader), setBroadcaster func(models.Broadcaster)) {
_setStreamAsConnected = setStreamAsConnected
_setBroadcaster = setBroadcaster
@ -83,27 +80,15 @@ func HandleConn(c *rtmp.Conn, nc net.Conn) {
return
}
rtmpOut, rtmpIn := io.Pipe()
_pipe = rtmpIn
log.Infoln("Inbound stream connected.")
_setStreamAsConnected()
pipePath := utils.GetTemporaryPipePath(fmt.Sprint(data.GetRTMPPortNumber()))
if !utils.DoesFileExists(pipePath) {
err := syscall.Mkfifo(pipePath, 0666)
if err != nil {
log.Fatalln(err)
}
}
_setStreamAsConnected(rtmpOut)
_hasInboundRTMPConnection = true
_rtmpConnection = nc
f, err := os.OpenFile(pipePath, os.O_RDWR, os.ModeNamedPipe)
_pipe = f
if err != nil {
log.Fatalln("unable to open", pipePath, "and will exit")
}
w := flv.NewMuxer(f)
w := flv.NewMuxer(rtmpIn)
for {
if !_hasInboundRTMPConnection {