Flutter工具基础webrtc

gdrx4gfi  于 2023-06-07  发布在  Flutter
关注(0)|答案(1)|浏览(123)

学习WebRTC的基本概念。
在此之前,我尝试了HTML和JS:

<!DOCTYPE html>
<html>
<head>
    <title>Basic WebRTC Page</title>
    <style>
        video {
            border: 1px solid black;
            --width: 25%;
            width: var(--width);
            height: calc(var(--width) * 0.75);
            margin: 0 0 20px 0;
            vertical-align: top;
        }
    </style>
</head>

<body>
    <video id="local" autoplay></video>
    <video id="remote" autoplay></video>

    <script charset="utf-8">
        const alice = new RTCPeerConnection();
        const bob = new RTCPeerConnection();

        alice.onicecandidate = e => {
            if (e.candidate) {
                bob.addIceCandidate(e.candidate);
            }
        }

        bob.onicecandidate = e => {
            if (e.candidate) {
                alice.addIceCandidate(e.candidate);
            }
        }

        navigator.mediaDevices.getUserMedia({
            video: true
        })
            .then(stream => {
                document.getElementById('local').srcObject = stream;
                alice.addStream(stream);
                return alice.createOffer();
            })
            .then(offer => alice.setLocalDescription(new RTCSessionDescription(offer)))
            .then(() => bob.setRemoteDescription(alice.localDescription))
            .then(() => bob.createAnswer())
            .then(answer => bob.setLocalDescription(new RTCSessionDescription(answer)))
            .then(() => alice.setRemoteDescription(bob.localDescription));

        bob.ontrack = e => {
            document.getElementById("remote").srcObject = e.streams[0];
        }

    </script>
</body>
</html>

这段代码在Web浏览器上工作没有任何问题。
现在,将该代码移植到flutter项目:

import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';

void main() {
  runApp(BasicApplication());
}

class BasicApplication extends StatelessWidget {
  const BasicApplication({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  late RTCPeerConnection alice;
  late RTCPeerConnection bob;

  MediaStream? localStream;

  late RTCVideoRenderer localRenderer;
  late RTCVideoRenderer remoteRenderer;

  @override
  void initState() {
    super.initState();

    localRenderer = RTCVideoRenderer();
    remoteRenderer = RTCVideoRenderer();

    initWebRTC();
  }

  Future<void> initWebRTC() async {
    try {
      await localRenderer.initialize();
      await remoteRenderer.initialize();

      final mediaStream = await navigator.mediaDevices.getUserMedia({
        'audio': false,
        'video': true,
      });

      print('Local stream has ${mediaStream.getVideoTracks().length} video tracks');

      alice = await createPeerConnection({});
      bob = await createPeerConnection({});

      localRenderer.srcObject = mediaStream;
      setState(() {
        localStream = mediaStream;
      });

      bob.onTrack = (event) {
        setState(() {
          remoteRenderer.srcObject = event.streams.first;
        });
      };

      final offer = await alice.createOffer({});
      await alice.setLocalDescription(offer);
      await bob.setRemoteDescription(offer);

      final answer = await bob.createAnswer({});
      await bob.setLocalDescription(answer);
      await alice.setRemoteDescription(answer);

    } catch (error) {
      print(error);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WebRTC Page'),
      ),
      body: Center(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Expanded(
              child: Container(
                decoration: BoxDecoration(
                  color: Colors.black ,
                  border: Border.all(color: Colors.black),
                ),
                margin: EdgeInsets.all(20),
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: RTCVideoView(
                    remoteRenderer,
                    objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
                    mirror: true,
                    placeholderBuilder: (BuildContext context) {
                      return Container(
                        color: Colors.grey,
                        child: Center(
                          child: Text('Waiting for remote video...'),
                        ),
                      );
                    },
                  ),
                ),
              ),
            ),
            Expanded(
              child: Container(
                decoration: BoxDecoration(
                  border: Border.all(color: Colors.black),
                ),
                margin: EdgeInsets.all(20),
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: RTCVideoView(
                    localRenderer,
                    objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
                    placeholderBuilder: (BuildContext context) {
                      return Container(
                        color: Colors.grey,
                        child: Center(
                          child: Text('Waiting for local video...'),
                        ),
                      );
                    },
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    localRenderer.dispose();
    remoteRenderer.dispose();
    alice.close();
    bob.close();
    super.dispose();
  }
}

任何人都可以向我解释为什么在chrome浏览器localRenderer返回我的网络摄像头图像,但remoterendered不能正常工作!
我的代码哪部分错了

m1m5dgzv

m1m5dgzv1#

修复了我在initWebRTC()方法中忘记的一些事情:

Future<void> initWebRTC() async {
    try {
      await localRenderer.initialize();
      await remoteRenderer.initialize();

      alice = await createPeerConnection({});
      bob = await createPeerConnection({});

      bob.onIceCandidate = (event) {
        if (event.candidate != null) {
          alice.addCandidate(event);
        }
      };

      alice.onIceCandidate = (event) {
        if (event.candidate != null) {
          bob.addCandidate(event);
        }
      };

      mediaStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
      localRenderer.srcObject = mediaStream;

      mediaStream!.getTracks().forEach((element) {
        alice.addTrack(element,mediaStream!);
      });

      bob.onTrack = (track) {
        remoteRenderer.srcObject = track.streams.first;
      };

      final offer = await alice.createOffer();
      await alice.setLocalDescription(offer);
      // print('Alice local description set: ${offer.sdp}');
      await bob.setRemoteDescription(offer);
      // print('Bob remote description set: ${offer.sdp}');

      final answer = await bob.createAnswer();
      await bob.setLocalDescription(answer);
      // print('Bob local description set: ${answer.sdp}');
      await alice.setRemoteDescription(answer);
      // print('Alice remote description set: ${answer.sdp}');

    } catch (error) {
      print(error);
    }
  }

相关问题