美文网首页
同Wi-Fi下获取硬件实时视频流(flutter篇)

同Wi-Fi下获取硬件实时视频流(flutter篇)

作者: 重驹 | 来源:发表于2021-04-15 17:31 被阅读0次

    一个网络请求方法不断的接收stream图片流事件,需要将这些图片流展示在Image控件上,这样就能够实现让图片变成视频的效果:
    直接上代码

    import 'dart:async';
    import 'dart:typed_data';
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    
    class TestApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'IPCamera'),
        );
      }
    }
    
    List<int> _bytes = [];
    Uint8List lastImageData = Uint8List(0);
    
    class MyHomePage extends StatefulWidget {
      final String title;
    
      MyHomePage({this.title});
    
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      final StreamController _streamController = StreamController();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text(widget.title),
            ),
            body: Column(
              children: [
                Container(
                  height: 60,
                  child: _topButton(),
                ),
                StreamBuilder(
                  builder: (BuildContext context, AsyncSnapshot snapshot) {
                    return Image.memory(
                        consolidateHttpClientResponseBytes(snapshot.data));
                  },
                  stream: _streamController.stream,
                  initialData: Uint8List(0),
                ),
              ],
            ));
      }
    
      Future _loadImagesData() async {
        var uri = Uri.parse("http://192.168.4.1:81/stream");
        var response = await http.Client().send(http.Request('GET',uri));
        response.stream.listen((value) {
          print(response.request.toString());
          _bytes.addAll(value);
          if (lastImageData.length == 36) {
            _streamController.sink.add(_bytes);
            _bytes = [];
          }
          lastImageData = Uint8List.fromList(value);
          print('当前数据字节长度${(lastImageData.length)}');
        });
      }
    
      Widget _topButton() {
        return Center(
          child: TextButton(
              style: ButtonStyle(
                foregroundColor: MaterialStateProperty.resolveWith(
                  (states) {
                    if (states.contains(MaterialState.focused) &&
                        !states.contains(MaterialState.pressed)) {
                      //获取焦点时的颜色
                      return Colors.green;
                    } else if (states.contains(MaterialState.pressed)) {
                      //按下时的颜色
                      return Colors.red;
                    }
                    //默认状态使用灰色
                    return Colors.white;
                  },
                ),
                padding: MaterialStateProperty.all(EdgeInsets.all(10)),
                minimumSize: MaterialStateProperty.all(Size(100, 50)),
                backgroundColor: MaterialStateProperty.resolveWith((states) {
                  //设置按下时的背景颜色
                  if (states.contains(MaterialState.pressed)) {
                    return Colors.yellowAccent[200];
                  }
                  //默认不使用背景颜色
                  return Colors.blue;
                }),
              ),
              onPressed: () {
                _loadImagesData();
              },
              child: Text('请求')),
        );
      }
    
      static consolidateHttpClientResponseBytes(data) {
        // response.contentLength is not trustworthy when GZIP is involved
        // or other cases where an intermediate transformer has been applied
        // to the stream.
        final List<List<int>> chunks = <List<int>>[];
        int contentLength = 0;
        chunks.add(data);
        contentLength += data.length;
        final Uint8List bytes = Uint8List(contentLength);
        int offset = 0;
        for (List<int> chunk in chunks) {
          bytes.setRange(offset, offset + chunk.length, chunk);
          offset += chunk.length;
        }
        return bytes;
      }
    }
    

    这里的网络请求用的是http框架,没使用dio框架,不知道是我不会用还是本身就没有这种对流请求的方法。

    导入的是http库:

      http: ^0.13.1
    

    其实这里有个问题,我不知道每次传回来的流啥时候是一张完整的图片流,通过观察数据,发现每次刚接收的时候长度是36,于是做了下处理。但实际上这样是不对的,暂时没有找到解决方案,如果有人知道的话,请不吝赐教。

    相关文章

      网友评论

          本文标题:同Wi-Fi下获取硬件实时视频流(flutter篇)

          本文链接:https://www.haomeiwen.com/subject/twqjlltx.html