WebRTC小demo

后端netty websocket作为 信令服务器。

研究了2天 代码是写死的 但是可以跑起来不用改什么东西。

这里直接粘贴上来吧。。 因为是demo 所以随便写的咯。

package webrtc;

import com.ContextSSLFactory;
import com.alibaba.fastjson.JSON;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;

import javax.net.ssl.SSLEngine;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

public class NettyWebRtcSvr {

    public static Map<String,Channel> users=new ConcurrentHashMap<>();

    public static void main(String[] args) throws InterruptedException {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(2);

        NioEventLoopGroup b = new NioEventLoopGroup(1);
        NioEventLoopGroup w = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap
                .group(b,w)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel channel) throws Exception {
                        System.out.println("connect");
                        channel.pipeline()
                                .addLast(new HttpServerCodec())

                                .addLast(new HttpObjectAggregator(65536))
                                .addLast(new ChunkedWriteHandler())
                                .addLast(new ChannelInboundHandlerAdapter(){
                                    @Override
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                        if (msg instanceof FullHttpRequest) {
                                            cyclicBarrier.await();


                                            FullHttpRequest request=(FullHttpRequest)msg;
                                            //拿到请求地址
                                            String uri = request.uri();
                                            //判断是不是websocket请求,如果是拿出我们传递的参数(我的是token)
                                            String origin = request.headers().get("Origin");
                                            if (null == origin) {
                                                ctx.close();
                                            } else {
                                                if (null != uri && uri.contains("/ws") && uri.contains("?")) {
                                                    String[] uriArray = uri.split("\\?");
                                                    if (null != uriArray && uriArray.length > 1) {
                                                        String[] paramsArray = uriArray[1].split("=");
                                                        if (null != paramsArray && paramsArray.length > 1) {
                                                            String uid = paramsArray[1];
                                                            Attribute<Object> uid1 = ctx.channel().attr(AttributeKey.valueOf("uid"));
                                                            uid1.set(uid);
                                                            users.put(uid,ctx.channel());

                                                        }
                                                    }
                                                    //重新设置请求地址
                                                    request.setUri("/ws");
                                                }
                                            }

                                        }
                                        super.channelRead(ctx, msg);
                                    }
                                })
                                .addLast(new WebSocketServerProtocolHandler("/ws"))
                                .addLast(new SimpleChannelInboundHandler<TextWebSocketFrame>() {
                                    @Override
                                    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
                                        ByteBuf content = msg.content();
                                        String msgstr = content.toString(Charset.defaultCharset());
                                        //System.out.println(msgstr);
                                        WebRtcMsg rtcState = JSON.parseObject(msgstr, WebRtcMsg.class);
                                        if (rtcState.getState() == RtcState.answer.state) {
                                            System.out.println("用户1收到 用户2 返回的 answer");

                                            Channel channel1 = users.get("1");
                                            TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(msgstr);
                                            channel1.writeAndFlush(textWebSocketFrame);
                                        }else if (rtcState.getState() == RtcState.offer.state) {
                                            System.out.println("用户1像 用户2 发送 offer");

                                            Channel channel1 = users.get("2");
                                            TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(msgstr);
                                            channel1.writeAndFlush(textWebSocketFrame);
                                        }else if (rtcState.getState() == RtcState.offer_condidate.state) {
                                            System.out.println("用户1像 用户2发送 condidate");
                                            Channel channel1 = users.get("2");
                                            TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(msgstr);
                                            channel1.writeAndFlush(textWebSocketFrame);
                                        }
                                    }

                                   
                                });
                    }
                });

        ChannelFuture future = bootstrap.bind(2333).sync();
        future.channel().closeFuture().sync();

    }
}

上面是服务端。 cyclicBarrier 主要是为了 我前端懒得 写。。
等2个都连接了 在发offer 免得发的时候 user2 client不在 。。
随便写 莫见怪。 主要是网上没有一个demo 能直接跑起来的。。差东差西。
我也看了好多 - -

package webrtc;

public enum RtcState {
    offer_condidate(1),
    offer(2),
    answer(3),
    ;


    public final int state;

    RtcState(Integer state){
        this.state=state;
    }

    public Integer getState() {
        return state;
    }


}
package webrtc;


public class WebRtcMsg {
    private Integer state;
    private String uid;
    private String condidate;
    private String desc;

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public Integer getState() {
        return state;
    }

    public void setState(Integer state) {
        this.state = state;
    }

    public String getCondidate() {
        return condidate;
    }

    public void setCondidate(String condidate) {
        this.condidate = condidate;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

下面是前端 这个是 发起端。 正常是一个页面就行 我就写死了

在这里插入代码片
```<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="https://webrtc.github.io/adapter/adapter.js" type="text/javascript"></script>


<body>
<video id="bend" controls="controls"> </video>
<video id="remoteVideo" controls="controls"> </video>
</body>

<script>
    var bend = document.getElementById("bend");
    var remoteVideo = document.getElementById("remoteVideo");
    client = new RTCPeerConnection();

    socket = new WebSocket("ws://localhost:2333/ws?uid=1");
    client.ontrack=function(event){
        remoteVideo.srcObject=event.streams[0];
    }

    socket.onmessage = function(event){
        var msg=event.data;
        var parse = JSON.parse(msg);
        console.info("当前用户为 2"+msg)

        console.info(msg)
        if (parse.state==3) {//answer
            client.setRemoteDescription(parse.desc)
        }else if (parse.state==2) {//offer
            // 当前用户是被发起用户 则setRemote后 再次发送 answer
            client.setRemoteDescription(parse.desc);
            client.createAnswer().then(desc=>{
                client.setLocalDescription(desc);
                var userInfo={"desc":desc,"uid":"2","state":"3"};
                socket.send(JSON.stringify(userInfo));
            })
        }else if (parse.state=1) {//offer_condidate

            console.info(" 收到 用户1 的condidate"+parse.condidate)
            client.addIceCandidate(new RTCIceCandidate(parse.condidate))
        }
    };

    socket.onopen=function (event){




        navigator.mediaDevices.getUserMedia({
            audio: true,
            video: true,
        }).then((stream) => {
            bend.srcObject=stream;
            stream.getTracks().forEach(function (track) {
                client.addTrack(track,stream);
            })
            client.createOffer().then((desc)=>{
                client.setLocalDescription(desc)
                //send server
                var userInfo={"desc":desc,"uid":"1","state":"2"};
                socket.send(JSON.stringify(userInfo))
            })
            client.onicecandidate=function (event) {
                var iceCandidate = event.candidate;
                var userInfo={"uid":"1","state":"1","condidate":iceCandidate};
                socket.send(JSON.stringify(userInfo))
            }

        })



    }


</script>
</html>


下面是接受端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="https://webrtc.github.io/adapter/adapter.js" type="text/javascript"></script>


<body>
<video id="bend" controls="controls"> </video>
<video id="remoteVideo" controls="controls"> </video>
</body>

<script>
    var bend = document.getElementById("bend");
    var remoteVideo = document.getElementById("remoteVideo");
    client = new RTCPeerConnection();

    socket = new WebSocket("ws://localhost:2333/ws?uid=2");
    client.ontrack=function(event){
        remoteVideo.srcObject=event.streams[0];
    }

    socket.onmessage = function(event){
        var msg=event.data;
        var parse = JSON.parse(msg);
        console.info("当前用户为 2"+msg)

        console.info(msg)
        if (parse.state==3) {//answer
            client.setRemoteDescription(parse.desc)
        }else if (parse.state==2) {//offer
            // 当前用户是被发起用户 则setRemote后 再次发送 answer
            client.setRemoteDescription(parse.desc);
            client.createAnswer().then(desc=>{
                client.setLocalDescription(desc);
                var userInfo={"desc":desc,"uid":"2","state":"3"};
                socket.send(JSON.stringify(userInfo));
            })
        }else if (parse.state=1) {//offer_condidate

            console.info(" 收到 用户1 的condidate"+parse.condidate)
            client.addIceCandidate(new RTCIceCandidate(parse.condidate))
        }
    };

    socket.onopen=function (event){
        navigator.mediaDevices.getUserMedia({
            audio: true,
            video: true,
        }).then((stream) => {
            bend.srcObject=stream;
            stream.getTracks().forEach(function (track) {
                client.addTrack(track,stream);
            })
        })
    }


</script>
</html>



turnserver 没有搞。  我不晓得为什么百度那么多 我就是跑不起来 。。。
配置一个样 都跑不起来 所以 内网玩玩 算了。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值