Open retamia opened 3 years ago
By the way, there is another issue here. If the vhost field is configured in the test-play.live.com vhost, and the rtmp address also includes the vhost parameter, it will cause the vhost field in the configuration to be ineffective. This part needs to be modified in the code. If the vhost field is configured in the vhost, when generating the srs_generate_rtmp_url, the vhost in the query should be removed. Otherwise, the generated URL will still be test-play.live.com, but according to the configuration, it should be test-push.live.com.
TRANS_BY_GPT3
Test code for Go
package main
import (
"bufio"
"bytes"
"errors"
"io"
"os/exec"
"syscall"
)
func processCmdPipeOut(pstdout *[]byte, pout io.ReadCloser, endpipe chan bool) {
r := bufio.NewReader(pout)
for {
//data, err := r.ReadBytes('\r')
data := []byte{}
var c byte
var e error
for {
c, e = r.ReadByte()
if e != nil {
break
}
data = append(data, c)
if c == '\r' || c == '\n' {
break
}
}
if len(data) > 0 {
print(string(data))
*pstdout = append(*pstdout, data...)
}
if e != nil {
break
}
}
endpipe <- true
}
func RunCmdWithCallback(cmdline string) ([]byte, error) {
var stdout, stderr []byte
var err error = nil
cmd := exec.Command("/bin/sh", "-c", cmdline)
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
pout, err0 := cmd.StdoutPipe()
perr, err1 := cmd.StderrPipe()
if err0 != nil || err1 != nil {
return nil, errors.New("pipe error")
}
chnum := 2
endpipe := make(chan bool, chnum)
defer close(endpipe)
cmd.Start()
// read data from StdoutPipe
go processCmdPipeOut(&stdout, pout, endpipe)
// read data from StderrPipe
go processCmdPipeOut(&stderr, perr, endpipe)
err = cmd.Wait()
for i := 0; i < chnum; i++ {
<-endpipe
}
return append(stdout, stderr...), err
}
func RunCmd2(cmdline string) ([]byte, []byte, error) {
cmd := exec.Command("/bin/sh", "-c", cmdline)
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
wo := bytes.NewBuffer(nil)
we := bytes.NewBuffer(nil)
cmd.Stdout = wo
cmd.Stderr = we
err := cmd.Run()
stdout := wo.Bytes()
stderr := we.Bytes()
return stdout, stderr, err
}
func main() {
ffprobeCmd := "ffprobe -hide_banner -rw_timeout 10000000 -of json -show_entries 'format:stream' -i 'rtmp://192.168.1.143:1935/test/lmt?vhost=test-play.live.com'"
sout, serr, _ := RunCmd2(ffprobeCmd)
println(string(sout))
println(string(serr))
ffmpegCmd := "ffmpeg -hide_banner -rw_timeout 10000000 -i 'rtmp://192.168.1.143:1935/test/lmt?vhost=test-play.live.com' -c:a copy -c:v libx264 -g 60 -preset veryfast -threads 8 -f flv -y 'rtmp://192.168.1.143:1935/test/lmt_trans?vhost=test-push.live.com'"
RunCmdWithCallback(ffmpegCmd)
}
TRANS_BY_GPT3
After taking a look, I didn't understand why the publish timeout occurred. Can you find the minimal reproducible path? For example, does this issue exist with a single SRS?
TRANS_BY_GPT3
I looked at it but didn't understand why there is a publish timeout. Can you find the minimum reproducible path? For example, does this problem occur with a single SRS?
I haven't found a better way to reproduce it yet. I suspect it may be a problem with the code in the Go coroutine that retrieves the StdoutPipe data, causing the log call in ffmpeg to block. I fixed it by modifying the Go code. However, it's also strange that this issue only occurs with RTMP, and there is no such phenomenon when using HTTP-FLV to pull the stream.
TRANS_BY_GPT3
Temporary solution found. It is the same phenomenon as this issue.
In the GO code, after ffprobe, ffmpeg is immediately called. When ffprobe's connection is disconnected, the edge has not yet completed the logic of on_all_client_stop, causing ffmpeg's connection to come up. The SRS edge status is still "init", which will cause ffmpeg to hang.
TRANS_BY_GPT3
Please do not comment randomly in the Issue, and do not go off-topic. Each Issue should only address one problem, otherwise it will be deleted directly. Before submitting an Issue, be sure to read FAQ #2716.
TRANS_BY_GPT3
Temporary solution found. It is the same phenomenon as this issue. After ffprobe in the GO code, ffmpeg is immediately called. When ffprobe's connection is disconnected, the edge has not yet completed the logic of on_all_client_stop, causing ffmpeg's connection to come up. The srs edge status is still init, which will cause ffmpeg to hang.
First of all, kudos to you. The cause of the issue has been identified. It seems that it would be better to return an error in this situation. When in an intermediate state, returning an error to the client can prevent it from getting stuck.
TRANS_BY_GPT3
Please do not comment randomly in the Issue, do not digress. Each Issue should only address one problem, otherwise it will be deleted directly. Before raising an Issue, be sure to read FAQ #2716.
GitHub has a feature to collapse comments.
TRANS_BY_GPT3
To fix the incorrect state of edge, we should refine the state machine of source, changing between publishing and unpublishing like DB transaction.
Description'
Please ensure that the markdown structure is maintained.
The first time using exec.Command in Go to execute FFprobe, and then executing FFmpeg, while using goroutines to read FFmpeg's StdoutPipe and StderrPipe, there is a probability of causing the streaming to freeze. If executing ffmpeg -i rtmp address in the terminal, the streaming freeze issue is automatically resolved. This phenomenon occurs when pulling streams from the edge vhost, but there is no such issue when pushing streams to the vhost.
5.0.11
http_server { enabled on; listen 8080; dir ./objs/nginx/html; }
http_api { enabled on; listen 1985; }
vhost test-push.live.com {
}
publish { mr off; }
}
vhost test-play.live.com {
}
3. Then, execute the following command using exec.Command and start a goroutine to read data from StdoutPipe and StderrPipe
4. The streaming gets stuck, and the SRS log shows "publish timeout", which can be reproduced with a certain probability. If it cannot be reproduced, you need to close the streaming and go process, and then start again from step 1.
Expected Behavior (Expect)
Able to stream normally.
TRANS_BY_GPT3