pion / mediadevices

Go implementation of the MediaDevices API.
https://pion.ly/
MIT License
520 stars 119 forks source link

go1.22.2 - example/webrtc Audio works, but video doesnt #572

Open CarlosHleb opened 2 months ago

CarlosHleb commented 2 months ago

Your environment.

What did you do?

I copy/pasted your code from the examples/webrtc and then ran CGO_ENABLED=1 go build my-module, followed the instructions on copy/pasting the SDP.

What did you expect?

I expected it to stream my camera and testaudio to browser

What happened?

it streamed testaudio audio just fine, but not the camera. testvideo streaming doesnt work as well.

Here is my full code

package main

import (
    "fmt"

    "github.com/pion/mediadevices"
    "github.com/pion/mediadevices/pkg/frame"
    "github.com/pion/mediadevices/pkg/prop"
    "github.com/pion/webrtc/v3"

    // If you don't like x264, you can also use vpx by importing as below
    // "github.com/pion/mediadevices/pkg/codec/vpx" // This is required to use VP8/VP9 video encoder
    // or you can also use openh264 for alternative h264 implementation
    // "github.com/pion/mediadevices/pkg/codec/openh264"
    // or if you use a raspberry pi like, you can use mmal for using its hardware encoder
    // "github.com/pion/mediadevices/pkg/codec/mmal"
    "github.com/pion/mediadevices/pkg/codec/opus" // This is required to use opus audio encoder
    "github.com/pion/mediadevices/pkg/codec/x264" // This is required to use h264 video encoder

    // Note: If you don't have a camera or microphone or your adapters are not supported,
    //       you can always swap your adapters with our dummy adapters below.
    _ "github.com/pion/mediadevices/pkg/driver/audiotest"
    _ "github.com/pion/mediadevices/pkg/driver/videotest"
    // _ "github.com/pion/mediadevices/pkg/driver/camera" // This is required to register camera adapter
    //_ "github.com/pion/mediadevices/pkg/driver/microphone" // This is required to register microphone adapter
)

func main() {
    config := webrtc.Configuration{
        ICEServers: []webrtc.ICEServer{
            {
                URLs: []string{"stun:stun.l.google.com:19302"},
            },
        },
    }

    // Wait for the offer to be pasted
    offer := webrtc.SessionDescription{}
    Decode(MustReadStdin(), &offer)

    // Create a new RTCPeerConnection
    x264Params, err := x264.NewParams()
    if err != nil {
        panic(err)
    }
    x264Params.Preset = x264.PresetMedium
    x264Params.BitRate = 500_000 // 500kbps

    opusParams, err := opus.NewParams()
    if err != nil {
        panic(err)
    }
    codecSelector := mediadevices.NewCodecSelector(
        mediadevices.WithVideoEncoders(&x264Params),
        mediadevices.WithAudioEncoders(&opusParams),
    )

    mediaEngine := webrtc.MediaEngine{}
    codecSelector.Populate(&mediaEngine)
    api := webrtc.NewAPI(webrtc.WithMediaEngine(&mediaEngine))
    peerConnection, err := api.NewPeerConnection(config)
    if err != nil {
        panic(err)
    }

    // Set the handler for ICE connection state
    // This will notify you when the peer has connected/disconnected
    peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
        fmt.Printf("Connection State has changed %s \n", connectionState.String())
    })

    s, err := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{
        Video: func(c *mediadevices.MediaTrackConstraints) {
            c.FrameFormat = prop.FrameFormat(frame.FormatI420)
            c.Width = prop.Int(640)
            c.Height = prop.Int(480)
        },
        Audio: func(c *mediadevices.MediaTrackConstraints) {
        },
        Codec: codecSelector,
    })
    if err != nil {
        panic(err)
    }

    for _, track := range s.GetTracks() {
        track.OnEnded(func(err error) {
            fmt.Printf("Track (ID: %s) ended with error: %v\n",
                track.ID(), err)
        })

        _, err = peerConnection.AddTransceiverFromTrack(track,
            webrtc.RtpTransceiverInit{
                Direction: webrtc.RTPTransceiverDirectionSendonly,
            },
        )
        if err != nil {
            panic(err)
        }
    }

    // Set the remote SessionDescription
    err = peerConnection.SetRemoteDescription(offer)
    if err != nil {
        panic(err)
    }

    // Create an answer
    answer, err := peerConnection.CreateAnswer(nil)
    if err != nil {
        panic(err)
    }

    // Create channel that is blocked until ICE Gathering is complete
    gatherComplete := webrtc.GatheringCompletePromise(peerConnection)

    // Sets the LocalDescription, and starts our UDP listeners
    err = peerConnection.SetLocalDescription(answer)
    if err != nil {
        panic(err)
    }

    // Block until ICE Gathering is complete, disabling trickle ICE
    // we do this because we only can exchange one signaling message
    // in a production application you should exchange ICE Candidates via OnICECandidate
    <-gatherComplete

    // Output the answer in base64 so we can paste it in browser
    fmt.Println(Encode(*peerConnection.LocalDescription()))

    // Block forever
    select {}
}
CarlosHleb commented 2 months ago

Doesnt work with screen as well(as the video track, after changing GetUserMedia as per docs).

CarlosHleb commented 2 months ago

just installed go1.19, same issue..

CarlosHleb commented 2 months ago

The video streaming bit seems to not working. camera not working as well.

rm4n0s commented 1 month ago

this happens to me as well, however on chrome the browser does not create any offer, so I switched to firefox that creates the offer but when connected the video is running without showing any image

jie-huang commented 3 weeks ago

This problem happens to me too. The audio works, but video does not. Anyone knows how to fix it? Thanks