同Wi-Fi下獲取硬件實(shí)時(shí)視頻流(flutter篇)

一個(gè)網(wǎng)絡(luò)請(qǐng)求方法不斷的接收stream圖片流事件,需要將這些圖片流展示在Image控件上,這樣就能夠?qū)崿F(xiàn)讓圖片變成視頻的效果:
直接上代碼

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('當(dāng)前數(shù)據(jù)字節(jié)長(zhǎng)度${(lastImageData.length)}');
    });
  }

  Widget _topButton() {
    return Center(
      child: TextButton(
          style: ButtonStyle(
            foregroundColor: MaterialStateProperty.resolveWith(
              (states) {
                if (states.contains(MaterialState.focused) &&
                    !states.contains(MaterialState.pressed)) {
                  //獲取焦點(diǎn)時(shí)的顏色
                  return Colors.green;
                } else if (states.contains(MaterialState.pressed)) {
                  //按下時(shí)的顏色
                  return Colors.red;
                }
                //默認(rèn)狀態(tài)使用灰色
                return Colors.white;
              },
            ),
            padding: MaterialStateProperty.all(EdgeInsets.all(10)),
            minimumSize: MaterialStateProperty.all(Size(100, 50)),
            backgroundColor: MaterialStateProperty.resolveWith((states) {
              //設(shè)置按下時(shí)的背景顏色
              if (states.contains(MaterialState.pressed)) {
                return Colors.yellowAccent[200];
              }
              //默認(rèn)不使用背景顏色
              return Colors.blue;
            }),
          ),
          onPressed: () {
            _loadImagesData();
          },
          child: Text('請(qǐng)求')),
    );
  }

  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;
  }
}

這里的網(wǎng)絡(luò)請(qǐng)求用的是http框架,沒(méi)使用dio框架,不知道是我不會(huì)用還是本身就沒(méi)有這種對(duì)流請(qǐng)求的方法。

導(dǎo)入的是http庫(kù):

  http: ^0.13.1

其實(shí)這里有個(gè)問(wèn)題,我不知道每次傳回來(lái)的流啥時(shí)候是一張完整的圖片流,通過(guò)觀察數(shù)據(jù),發(fā)現(xiàn)每次剛接收的時(shí)候長(zhǎng)度是36,于是做了下處理。但實(shí)際上這樣是不對(duì)的,暫時(shí)沒(méi)有找到解決方案,如果有人知道的話,請(qǐng)不吝賜教。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開(kāi)了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    余生動(dòng)聽(tīng)閱讀 10,914評(píng)論 0 11
  • 彩排完,天已黑
    劉凱書法閱讀 4,497評(píng)論 1 3
  • 表情是什么,我認(rèn)為表情就是表現(xiàn)出來(lái)的情緒。表情可以傳達(dá)很多信息。高興了當(dāng)然就笑了,難過(guò)就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,895評(píng)論 2 7

友情鏈接更多精彩內(nèi)容