video_windows_live 0.0.1 copy "video_windows_live: ^0.0.1" to clipboard
video_windows_live: ^0.0.1 copied to clipboard

unlisted

Um plugin sobre video para Windows

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:video_windows_live/video_player_vms.dart';

void main() {
  runApp(
    const MaterialApp(
      home: VMSStressTestApp(),
      debugShowCheckedModeBanner: false,
    ),
  );
}

class VMSStressTestApp extends StatefulWidget {
  const VMSStressTestApp({super.key});

  @override
  State<VMSStressTestApp> createState() => _VMSStressTestAppState();
}

class _VMSStressTestAppState extends State<VMSStressTestApp> {
  final int rows = 4;
  final int cols = 4;
  late final List<VideoPlayerVMSController> _controllers;
  late final List<TextEditingController> _urlControllers;

  @override
  void initState() {
    super.initState();
    int total = rows * cols;
    _controllers = List.generate(total, (_) => VideoPlayerVMSController());
    _urlControllers = List.generate(total, (index) {
      return TextEditingController(
        text: linkVideo(index),
      );
    });
    _initializePlayers();
  }

  String linkVideo(int index) {
    List<String> _links = [
      "https://live35.analitico.app.br/stream/get/homologacaopt00.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live36.analitico.app.br/stream/get/associacaodas00.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live36.analitico.app.br/stream/get/associacaodas01.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://c.vms.tutorsa.cloud/stream/get/associacaodas02.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://c.vms.tutorsa.cloud/stream/get/associacaodas03.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor06.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor07.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor08.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor11.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor12.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor13.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor14.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live12.analitico.app.br/stream/get/associacaomor20.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live9.analitico.app.br/stream/get/associacaomor18.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live12.analitico.app.br/stream/get/associacaomor19.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live23.analitico.app.br/stream/get/associacaomor23.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live23.analitico.app.br/stream/get/associacaomor24.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live26.analitico.app.br/stream/get/associacaomor25.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor00.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor01.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor02.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor03.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live3.analitico.app.br/stream/get/associacaomor04.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live8.protenet.com.br/stream/get/associacaomor21.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw",
      "https://live42.analitico.app.br/stream/get/atacadaolivre02.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw"
    ];
    return _links[index];

      switch (index) {
      case 0 :
      return 'https://live42.analitico.app.br/stream/get/atacadaolivre02.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw';
      case 1:
      return 'https://live3.analitico.app.br/stream/get/associacaomor04.m3u8?token=nSX45IJaVe0kP2TuUMh9ud8Xbf0wkw';
      case 2:
      return 'rtsp://teste:read1010nt@45.190.52.116:554/h264/ch1/main/av_stream';
      case 3:
      return 'rtsp://admin:Pr0t3adm@192.168.0.27:1554/h264/ch1/main/av_stream';
      default:
      return '';
      }
  }

  Future<void> _initializePlayers() async {
    for (var controller in _controllers) {
      await controller.initialize();
    }
  }

  @override
  void dispose() {
    for (var controller in _controllers) {
      controller.dispose();
    }
    for (var urlController in _urlControllers) {
      urlController.dispose();
    }
    super.dispose();
  }

  void _playAll() {
    for (int i = 0; i < _controllers.length; i++) {
      if (_controllers[i].status == VideoPlayerStatus.idle ||
          _controllers[i].status == VideoPlayerStatus.error) {
        _controllers[i].play(_urlControllers[i].text);
      }
    }
  }

  void _stopAll() {
    for (int i = 0; i < _controllers.length; i++) {
      _controllers[i].stop();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('VMS Stress Test - 36 Cameras (6x6)'),
        backgroundColor: Colors.blueGrey[900],
        foregroundColor: Colors.white,
        actions: [
          IconButton(
            icon: const Icon(Icons.play_arrow),
            onPressed: _playAll,
            tooltip: 'Play All',
          ),
          IconButton(
            icon: const Icon(Icons.stop),
            onPressed: _stopAll,
            tooltip: 'Stop All',
          ),
        ],
      ),
      backgroundColor: Colors.black,
      body: Column(
        children: List.generate(rows, (row) {
          return Expanded(
            child: Row(
              children: List.generate(cols, (col) {
                int index = row * cols + col;
                return Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(1.0),
                    child: PlayerCell(
                      controller: _controllers[index],
                      urlController: _urlControllers[index],
                      index: index,
                    ),
                  ),
                );
              }),
            ),
          );
        }),
      ),
    );
  }
}

class PlayerCell extends StatelessWidget {
  final VideoPlayerVMSController controller;
  final TextEditingController urlController;
  final int index;

  const PlayerCell({
    super.key,
    required this.controller,
    required this.urlController,
    required this.index,
  });

  @override
  Widget build(BuildContext context) {
    return ListenableBuilder(
      listenable: controller,
      builder: (context, _) {
        return GestureDetector(
          onTap: () {
            if (controller.status == VideoPlayerStatus.idle ||
                controller.status == VideoPlayerStatus.error) {
              controller.play(urlController.text);
            } else {
              controller.stop();
            }
          },
          child: Container(
            decoration: BoxDecoration(
              color: Colors.grey[900],
              border: Border.all(
                color: _getStatusColor(controller.status),
                width: 1,
              ),
            ),
            child: Stack(
              children: [
                ClipRect(
                  child: SizedBox.expand(
                    child: FittedBox(
                      fit: BoxFit.cover,
                      child: SizedBox(
                        width: 1280,
                        height: 720,
                        child: VideoPlayerVMS(controller: controller),
                      ),
                    ),
                  ),
                ),
                Positioned.fill(child: _buildOverlay()),
                Positioned(
                  top: 2,
                  left: 2,
                  child: Container(
                    padding: const EdgeInsets.symmetric(
                      horizontal: 4,
                      vertical: 2,
                    ),
                    color: Colors.black54,
                    child: Text(
                      "CAM ${index + 1}",
                      style: const TextStyle(color: Colors.white, fontSize: 10),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Widget _buildOverlay() {
    switch (controller.status) {
      case VideoPlayerStatus.buffering:
        return Container(
          color: Colors.black38,
          child: const Center(
            child: SizedBox(
              width: 20,
              height: 20,
              child: CircularProgressIndicator(
                strokeWidth: 2,
                valueColor: AlwaysStoppedAnimation<Color>(Colors.orangeAccent),
              ),
            ),
          ),
        );
      case VideoPlayerStatus.idle:
        return Container(
          color: Colors.black26,
          child: Center(
            child: Icon(
              Icons.play_circle_fill,
              size: 30,
              color: Colors.white.withOpacity(0.8),
            ),
          ),
        );
      case VideoPlayerStatus.error:
        return Container(
          color: Colors.black54,
          child: const Center(
            child: Icon(Icons.error, color: Colors.redAccent, size: 30),
          ),
        );
      case VideoPlayerStatus.playing:
      default:
        return const SizedBox.shrink();
    }
  }

  Color _getStatusColor(VideoPlayerStatus status) {
    switch (status) {
      case VideoPlayerStatus.playing:
        return Colors.greenAccent.withOpacity(0.5);
      case VideoPlayerStatus.buffering:
        return Colors.orangeAccent.withOpacity(0.5);
      case VideoPlayerStatus.error:
        return Colors.redAccent.withOpacity(0.5);
      case VideoPlayerStatus.idle:
      default:
        return Colors.white24;
    }
  }
}