Воспроизведение мультимедиа Flutter — аудио/видео

Привет всем разработчикам флаттера

В вашей повседневной разработке вы можете столкнуться с проблемой воспроизведения мультимедиа, как воспроизвести удаленное видео или аудио, любые проблемы с воспроизведением,

Здесь мы увидим, как играть Video а также Audio файл из Интернета, Активы и Локальные.

В этом демо я буду использовать три плагина.

video_player
audioplayers
file_picker

Итак, используя эти три плагина, мы собираемся создать демонстрационный проект для MediaPlayBack.

Давайте начнем,

Зависимости

Добавьте следующие зависимости в pubspec.yaml

video_player: ^0.10.2+1
file_picker: ^1.4.0
audioplayers: ^0.13.2

Сначала мы видим, как воспроизводить видео, затем переходим к аудио.

видео

Вот как продвигаться с видео

Разрешение

Предупреждение: видеопроигрыватель не работает на симуляторах iOS. Во время разработки/тестирования необходимо использовать устройство iOS.

Добавьте следующую запись в файл Info.plist, расположенный в папке /ios/Runner/Info.plist:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

Добавьте ниже разрешение в iOS для file_picker

<key>NSAppleMusicUsageDescription</key>
<string>Explain why your app uses music</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Explain why your app uses photo library</string>

Убедитесь, что в вашем файле манифеста Android, расположенном в /android/app/src/main/AndroidManifest.xml, присутствует следующее разрешение:

<uses-permission android:name="android.permission.INTERNET"/>

Поддерживаемые форматы

В iOS вспомогательным проигрывателем является AVPlayer. Поддерживаемые форматы различаются в зависимости от версии iOS. Класс AVURLAsset имеет audiovisualTypes, которые вы можете запрашивать для поддерживаемых форматов av.
На Android вспомогательным проигрывателем является ExoPlayer, список поддерживаемых форматов см. здесь.

Видео из Интернета

Объявите в своем коде переменную, которая VideoPlayerControllerэтот мы собираемся использовать с ним VideoPlayer

VideoPlayerController _videoPlayerController = VideoPlayerController.network(
      "https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_2mb.mp4",);

Теперь, чтобы инициализировать контроллер, вызовите это в initState

  @override
  void initState() {
    super.initState();
    _videoPlayerController
      ..initialize().then((_) {
        setState(() {});
      });
    _videoPlayerController..addListener(() {
      setState(() {
        
      });
    });
  }

Теперь, чтобы визуализировать Player, нам нужно добавить код пользовательского интерфейса.

_videoPlayerController.value.initialized
    ? AspectRatio(
        aspectRatio: _videoPlayerController.value.aspectRatio,
        child: VideoPlayer(_videoPlayerController),
        )
    : Container(),

В приведенном выше коде мы сделали следующее. После инициализации проигрывателя мы показываем VideoPlayer но мы используем AspectRatio тот используется для автоматического изменения размера видео по высоте и ширине

По умолчанию VideoPlayer не предоставляет элементы управления для использования, которые нам нужны для разработки и обработки их самостоятельно.

Center(
    child: IconButton(
        icon: Icon(
            _videoPlayerController.value.isPlaying ? Icons.pause : Icons.play_arrow,
        ),
        onPressed: () {
            _videoPlayerController.value.isPlaying ? _videoPlayerController.pause() : _videoPlayerController.play();
            setState(() {
                
            });
        },
    ),
)

здесь в приведенном выше коде _videoPlayerController.play() начнется воспроизведение видео _videoPlayerController.pause() поставит плеер на паузу

@override
void dispose() {
    _videoPlayerController.removeListener(() {});
    _videoPlayerController.dispose();
    super.dispose();
}

Вот полный код для воспроизведения видео из Интернета

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

class VideoNetwork extends StatefulWidget {
  @override
  _VideoNetworkState createState() => _VideoNetworkState();
}

class _VideoNetworkState extends State<VideoNetwork> {
  VideoPlayerController _videoPlayerController = VideoPlayerController.network(
      "https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_2mb.mp4",);

  @override
  void initState() {
    super.initState();
    _videoPlayerController
      ..initialize().then((_) {
        _videoPlayerController.setLooping(true);
        setState(() {});
      });
    _videoPlayerController..addListener(() {
      setState(() {
      });
    });
  }

  @override
  void dispose() {
    _videoPlayerController.removeListener(() {});
    _videoPlayerController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Video From Network"),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            _videoPlayerController.value.initialized
                ? AspectRatio(
                    aspectRatio: _videoPlayerController.value.aspectRatio,
                    child: VideoPlayer(_videoPlayerController),
                  )
                : Container(),
            Center(
              child: IconButton(
                icon: Icon(
                  _videoPlayerController.value.isPlaying ? Icons.pause : Icons.play_arrow,
                ),
                onPressed: () {
                   _videoPlayerController.value.isPlaying ? _videoPlayerController.pause() : _videoPlayerController.play();
                   setState(() {
                     
                   });
                },
              ),
            )
          ],
        ),
      ),
    );
  }
}

Видео из активов

Единственное существенное различие между воспроизведением видео из интернета и активами — это VideoPlayerController часть

VideoPlayerController _videoPlayerController = VideoPlayerController.asset(
      "assets/video.mp4",);

Для воспроизведения видео из активов вместо VideoPlayerController.network мы используем VideoPlayerController.asset а в остальном все работает как указано выше

Видео из файла

Единственным существенным отличием между воспроизведением видео из Интернета и локального является VideoPlayerController часть

VideoPlayerController _videoPlayerController = VideoPlayerController.file(videoFile);

Для воспроизведения видео с Local вместо VideoPlayerController.network мы используем VideoPlayerController.file а в остальном все работает как указано выше

Итак, чтобы получить файл, мы будем использовать file_picker плагин

Выберите видеофайл

_pickVideoFileFrom(context) async {
    File videoFile = await FilePicker.getFile(type: FileType.VIDEO);
    if (videoFile == null) {
        print("Video Picked is null");
    }
    Navigator.of(context).push(MaterialPageRoute(builder: (context) {
        return VideoFile(
            file: videoFile,
        );
    }));
}

Приведенный выше код работает, чтобы выбрать файл из локального хранилища и передать файл на новую страницу, где будет воспроизводиться видео.

File videoFile = await FilePicker.getFile(type: FileType.VIDEO);

этот код указывает, какой тип файла я должен получить. Для видео мы использовали FileType.VIDEO и для аудио мы будем использовать FileType.AUDIO

окончательный, но важный dispose

@override
void dispose() {
    _videoPlayerController.removeListener(() {});
    _videoPlayerController.dispose();
    super.dispose();
}

Аудио

Начнем с аудио

AudioPlayer для удаленных файлов

Инициализировать аудиоплеер

AudioPlayer audioPlayer = AudioPlayer();

чтобы начать воспроизведение удаленного вызова файла

await audioPlayer.play(
        "https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_2MG.mp3");

приостановить или возобновить


audioPlayer.pause();

await audioPlayer.resume();

Примечание. Этот плагин не предоставляет никакого пользовательского интерфейса для вашего плеера, нам нужно создать пользовательский интерфейс самостоятельно.

Чтобы прослушать состояние игрока, нам нужно прослушать onPlayerStateChanged

audioPlayer.onPlayerStateChanged.listen((AudioPlayerState state) {
      print("$state");
});

Чтобы прослушать обновления продолжительности проигрывателя, нам нужно прослушать onPlayerStateChanged

audioPlayer.onAudioPositionChanged.listen((Duration p) async {
      print('Current position: $p');
});

Чтобы получить длину песни, используйте audioPlayer.getDuration()

await audioPlayer.getDuration();

окончательный, но важный dispose

@override
void dispose() async {
    await audioPlayer.release();
    await audioPlayer.dispose();
    super.dispose();
}

Вот полный код AudioPlayer — Воспроизведение из Интернета

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

class AudioNetwork extends StatefulWidget {
  @override
  _AudioNetworkState createState() => _AudioNetworkState();
}

class _AudioNetworkState extends State<AudioNetwork> {
  AudioPlayer audioPlayer = AudioPlayer();

  bool isPlaying = false;
  bool isStarted = false;
  Duration duration;
  int time;

  String timeLeft = "";
  double progress = 0.0;

  startPlaying() async {
    if (!isStarted) {
      await audioPlayer.play(
          "https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_2MG.mp3");
      isStarted = true;
    } else
      await audioPlayer.resume();
    
  }

  getTimeLeft() {
    if (duration == null) {
      setState(() {
        timeLeft = "Time Left 0s";
      });
    } else {
      setState(() {
        timeLeft = "Time Left ${duration.inSeconds}s";
      });
    }
  }

  getProgress() {
    if (time == null || duration == null) {
      setState(() {
        progress = 0.0;
      });
    } else {
      setState(() {
        progress = time / (duration.inMilliseconds);
      });
    }
  }

  @override
  void initState() {
    super.initState();
    audioPlayer.onAudioPositionChanged.listen((Duration p) async {
      print('Current position: $p');
      time = await audioPlayer.getDuration();
      duration = p;
      if (duration == null) {
        timeLeft = "Time Left 0s/0s";
      } else {
        timeLeft = "Time Left ${duration.inSeconds}s/${time / 1000}s";
      }
      if (time == null || duration == null) {
        progress = 0.0;
      } else {
        progress = (duration.inMilliseconds) / time;
      }
      print(progress);
      setState(() {});
    });
    audioPlayer.onPlayerStateChanged.listen((AudioPlayerState state) {
      print("$state");
      if (state == AudioPlayerState.PLAYING) {
        setState(() {
          isPlaying = true;
        });
      } else {
        if (mounted) {
          setState(() {
            isPlaying = false;
          });
        }
      }
    });
  }

  @override
  void dispose() async {
    await audioPlayer.release();
    await audioPlayer.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Audio Player"),
      ),
      body: Container(
        padding: const EdgeInsets.all(16.0),
        child: Center(
          child: Column(
            children: <Widget>[
              LinearProgressIndicator(
                value: progress,
              ),
              SizedBox(
                height: 16.0,
              ),
              Text(timeLeft),
              SizedBox(
                height: 16.0,
              ),
              Center(
                child: IconButton(
                  icon: Icon(
                    isPlaying ? Icons.pause : Icons.play_arrow,
                  ),
                  onPressed: () {
                    isPlaying ? audioPlayer.pause() : startPlaying();
                    setState(() {});
                  },
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

AudioPlayer для локальных файлов

Основное отличие от воспроизведения удаленных файлов и локальных файлов заключается только в том, как мы начинаем воспроизведение, в то время, когда мы вызываем play нам нужно передать еще один параметр с именем isLoacal воспроизвести локальный файл

Прежде всего нам нужно выбрать файл и отправить его на страницу AudioPlayer, где он будет воспроизводиться.

_pickAudioFileFrom(context) async {
    File audioFile = await FilePicker.getFile(type: FileType.AUDIO);
    if (audioFile == null) {
        print("Audio Picked is null");
    }
    Navigator.of(context).push(MaterialPageRoute(builder: (context) {
        return AudioLocal(
            file: audioFile,
        );
    }));
}

Воспроизведение аудиофайла

await audioPlayer.play(audioFile.path, isLocal: true);

окончательный, но важный dispose

@override
void dispose() async {
    await audioPlayer.release();
    await audioPlayer.dispose();
    super.dispose();
}

Я предоставлю ссылку на github внизу

AudioPlayer для активов

Воспроизведение аудиофайла из ресурсов отличается от других режимов

Инициализировать аудиоплеер

static AudioPlayer audioPlayer = AudioPlayer();
  
AudioCache audioPlayerCache = AudioCache(
    fixedPlayer: audioPlayer
);

чтобы начать воспроизведение удаленного вызова файла

await audioPlayerCache.play("audio.mp3");

Остальные все такие же, как и в других режимах

окончательный, но важный dispose

@override
void dispose() async {
    await audioPlayer.release();
    await audioPlayer.dispose();
    super.dispose();
}

Вот полный код AudioPlayer — Воспроизведение из активов

import 'package:audioplayers/audio_cache.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';

class AudioAssets extends StatefulWidget {
  @override
  _AudioAssetsState createState() => _AudioAssetsState();
}

class _AudioAssetsState extends State<AudioAssets> {
  static AudioPlayer audioPlayer = AudioPlayer();
  
  AudioCache audioPlayerCache = AudioCache(
    fixedPlayer: audioPlayer
  );

  bool isPlaying = false;
  bool isStarted = false;
  Duration duration;
  int time;

  String timeLeft = "";
  double progress = 0.0;

  startPlaying() async{
    if(!isStarted) {
      await audioPlayerCache.play(
        "audio.mp3");
      isStarted = true;
    }
    else await audioPlayer.resume();
    
  }

  getTimeLeft() {
    if(duration == null) {
      setState(() {
       timeLeft = "Time Left 0s"; 
      });
    } else {
      setState(() {
       timeLeft = "Time Left ${duration.inSeconds}s"; 
      });
    }
  }
  getProgress()  {
    if(time == null || duration == null) {
      setState(() {
       progress = 0.0; 
      });
    } else {
      setState(() {
        progress = time / (duration.inMilliseconds);
      });
    }
    
  }

  @override
  void initState() {
    super.initState();
    audioPlayer.onAudioPositionChanged.listen((Duration p) async {
      print('Current position: $p');
      time = await audioPlayer.getDuration();
        duration = p;
      if(duration == null) {
       timeLeft = "Time Left 0s/0s"; 
    } else {
       timeLeft = "Time Left ${duration.inSeconds}s/${time/1000}s"; 
    }
    if(time == null || duration == null) {
       progress = 0.0; 
    } else {
        progress = (duration.inMilliseconds)/ time ;
    }
    print(progress);
    setState(() {
      
    });
    });
    audioPlayer.onPlayerStateChanged.listen((AudioPlayerState state) {
      print("$state");
      if (state == AudioPlayerState.PLAYING) {
        setState(() {
          isPlaying = true;
        });
      } else {
        if(mounted) {
          setState(() {
            isPlaying = false;
          });
        }
      }
    });
  }

  @override
  void dispose() async {
    await audioPlayer.release();
    await audioPlayer.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Audio Player"),
      ),
      body: Container(
        padding: const EdgeInsets.all(16.0),
        child: Center(
          child: Column(
            children: <Widget>[
              LinearProgressIndicator(
                value: progress,
              ),
              SizedBox(
                height: 16.0,
              ),
              Text(timeLeft),
              SizedBox(
                height: 16.0,
              ),
              Center(
                child: IconButton(
                  icon: Icon(
                    isPlaying ? Icons.pause : Icons.play_arrow,
                  ),
                  onPressed: () {
                    isPlaying ? audioPlayer.pause() : startPlaying();
                    setState(() {});
                  },
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *