'WebRTC video not showing
I have a streaming server that receives RTMP video inside RTP packets and publishes these packets to a web browser. The connection is established, but no video is shown. My server looks like this:
func main() {
http.HandleFunc("/createPeerConnection", createPeerConnection)
panic(http.ListenAndServe(":8080", nil))
}
func createPeerConnection(w http.ResponseWriter, r *http.Request) {
peerConnection, err := webrtc.NewPeerConnection(webrtc.Configuration{})
if err != nil {
panic(err)
}
// Create a video track
videoTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: "video/vp8"}, "video", "pion")
if err != nil {
panic(err)
}
rtpSender, err := peerConnection.AddTrack(videoTrack)
if err != nil {
panic(err)
}
processRTCP(rtpSender)
// Create a video track
audioTrack, err := webrtc.NewTrackLocalStaticSample(webrtc.RTPCodecCapability{MimeType: "audio/opus"}, "audio", "pion")
if err != nil {
panic(err)
}
rtpSender, err = peerConnection.AddTrack(audioTrack)
if err != nil {
panic(err)
}
processRTCP(rtpSender)
var offer webrtc.SessionDescription
if err := json.NewDecoder(r.Body).Decode(&offer); err != nil {
return
}
if err := peerConnection.SetRemoteDescription(offer); err != nil {
panic(err)
}
answer, err := peerConnection.CreateAnswer(nil)
if err != nil {
panic(err)
} else if err = peerConnection.SetLocalDescription(answer); err != nil {
panic(err)
}
response, err := json.Marshal(answer)
if err != nil {
panic(err)
}
w.Header().Set("Content-Type", "application/json")
if _, err := w.Write(response); err != nil {
panic(err)
}
go rtpToTrack(videoTrack, &codecs.VP8Packet{}, 90000, 5004)
go rtpToTrack(audioTrack, &codecs.OpusPacket{}, 48000, 5006)
}
func processRTCP(rtpSender *webrtc.RTPSender) {
go func() {
rtcpBuf := make([]byte, 1500)
for {
if _, _, rtcpErr := rtpSender.Read(rtcpBuf); rtcpErr != nil {
return
}
}
}()
}
func rtpToTrack(track *webrtc.TrackLocalStaticSample, depacketizer rtp.Depacketizer, sampleRate uint32, port int) {
listener, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("10.0.1.166"), Port: port})
if err != nil {
panic(err)
}
defer func() {
if err = listener.Close(); err != nil {
panic(err)
}
}()
sampleBuffer := samplebuilder.New(10, depacketizer, sampleRate)
for {
inboundRTPPacket := make([]byte, 1500) // UDP MTU
packet := &rtp.Packet{}
n, _, err := listener.ReadFrom(inboundRTPPacket)
if err != nil {
panic(fmt.Sprintf("error during read: %s", err))
}
if err = packet.Unmarshal(inboundRTPPacket[:n]); err != nil {
panic(err)
}
sampleBuffer.Push(packet)
for {
sample := sampleBuffer.Pop()
if sample == nil {
break
}
if writeErr := track.WriteSample(*sample); writeErr != nil {
panic(writeErr)
}
}
}
}
And my sample javascript looks like this:
const setupRTMP = () => {
const configuration = {
iceServers: [
{ urls: "stun:stun.l.google.com:19302" },
{ urls: "stun:stun.1.google.com:19302" },
//Prod
{
urls: "turn:34.243.91.76:3478",
username: "XXXXXXX",
credential: "XXX",
},
// Staging
{
urls: "turn:3.249.123.75:3478",
username: "XXXXXXX",
credential: "XXX",
},
],
};
let pc = new RTCPeerConnection(configuration);
pc.ontrack = function (event) {
console.error(event);
let el = document.getElementById("video-display");
el.srcObject = event.streams[0];
el.autoplay = true;
el.controls = true;
};
pc.addTransceiver('video')
pc.addTransceiver('audio')
pc.createOffer()
.then((offer) => {
pc.setLocalDescription(offer);
return fetch(
"http://X.X.X.X:8080/createPeerConnection",
{
method: "post",
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",
},
body: JSON.stringify(offer),
}
);
})
.then((res) => res.json())
.then((res) => pc.setRemoteDescription(res))
.catch((err) => console.log(err));
};
setupRTMP();
I tried streaming using these two commands:
ffmpeg -re -i <rtmp_server> -vn -acodec libopus -f rtp rtp://<go_server>:5006 -vcodec copy -an -f rtp rtp://<go_server>:5004 -sdp_file video.sdp
ffmpeg -i <rtmp_server> -an -vcodec libvpx -cpu-used 5 -deadline 1 -g 10 -error-resilient 1 -auto-alt-ref 1 -f rtp rtp://<go_server>:5004 -vn -c:a libopus -f rtp rtp:/<go_server>:5006
When analyzing the webrtc internals, I can see that the connection is established, and I know the video is getting to the server and is being written to the tracks. Can anyone find the problem here? Thank you
EDIT
How to run the code
- Clone this repo
- Run
python3 -m http.server - Clone this repo
- Replace the CHANGEME by your private IP (
hostname -Ion Linux) on main.go - Run
go run main.go - Run
ffmpeg -re -i <someMediaFileOnYourComputer> -vn -acodec libopus -f rtp rtp://<go_server>:5006 -vcodec copy -an -f rtp rtp://<go_server>:5004 -sdp_file video.sdp - The video/image streamed should appear on the website, but it doesn't
Solution 1:[1]
Your solution is use FFmpeg to covert RTMP to RTP, then covert RTP to WebRTC, that is too complex. The more simple and straight forward solution is use a media server to covert RTMP to WebRTC.
SRS supports coverting RTMP to WebRTC, or vice versa, please read RTMP to RTC.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Winlin |
