티스토리 뷰

Flutter는 다양한 플러그인을 통해 강력하고 유연한 기능을 제공하며, 동영상 재생도 그 중 하나입니다. 본 포스팅에서는 Flutter에서 video_player 플러그인을 활용해 동영상을 재생하는 방법을 자세히 살펴보겠습니다. 코드 예제와 함께 주요 설정 및 활용 팁도 포함되어 있어 Flutter 초보자와 전문가 모두에게 유용한 정보를 제공합니다.

참고. Play and pause a video

Flutter에서 동영상 재생이 중요한 이유

앱 개발 과정에서 동영상 재생은 중요한 멀티미디어 기능 중 하나입니다. 동영상은 교육 앱, 스트리밍 서비스, 소셜 미디어 플랫폼 등에서 필수적인 요소로 활용되며, Flutter의 video_player 플러그인은 다양한 플랫폼에서 이러한 요구를 충족시키는 데 필요한 모든 기능을 제공합니다.

video_player 플러그인 설치 및 설정

Flutter에서 동영상 재생을 구현하려면 먼저 video_player 플러그인을 설치해야 합니다. 아래 단계에 따라 설치를 진행하세요.

1. 플러그인 설치

pubspec.yaml 파일에 다음과 같이 video_player 의존성을 추가하세요.

dependencies:
  video_player: ^2.5.2

이후 아래 명령어를 실행하여 패키지를 설치합니다.

flutter pub get

2. 플랫폼별 추가 설정

Android

  • AndroidManifest.xml 파일에 인터넷 권한을 추가합니다.
    <uses-permission android:name="android.permission.INTERNET"/>

iOS

  • iOS 프로젝트에서 Info.plist 파일을 열어 아래 코드를 추가합니다.
    <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    </dict>

Flutter에서 동영상 재생 기본 구현

이제 기본적인 동영상 재생 기능을 구현해보겠습니다.

1. Controller 초기화

동영상 재생을 위해서는 VideoPlayerController를 생성하고 초기화해야 합니다. 네트워크 URL이나 로컬 파일 경로를 사용할 수 있습니다.

네트워크 URL 사용 예제

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

class VideoPlayerScreen extends StatefulWidget {
  @override
  _VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network(
      'https://www.example.com/sample-video.mp4',
    )..initialize().then((_) {
        setState(() {}); // 초기화 완료 후 화면 갱신
      });
  }

  @override
  void dispose() {
    _controller.dispose(); // 메모리 누수 방지
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Video Player Example')),
      body: Center(
        child: _controller.value.isInitialized
            ? AspectRatio(
                aspectRatio: _controller.value.aspectRatio,
                child: VideoPlayer(_controller),
              )
            : CircularProgressIndicator(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _controller.value.isPlaying
                ? _controller.pause()
                : _controller.play();
          });
        },
        child: Icon(
          _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ),
    );
  }
}

2. 플레이어에 추가 기능 구현

재생 및 일시 정지

플레이 버튼을 눌러 동영상을 재생하거나 일시 정지할 수 있습니다.

동영상 진행 상태

VideoPlayerControllervalue 속성을 사용해 현재 재생 시간이나 동영상 길이를 가져올 수 있습니다.

Text(
  '현재 재생 시간: ${_controller.value.position.inSeconds}s',
)

고급 기능: Chewie로 사용자 경험 향상

video_player는 강력하지만 기본 제공 기능만으로는 제한이 있을 수 있습니다. 이 경우 Chewie 패키지를 사용하면 보다 직관적인 사용자 경험을 제공할 수 있습니다.

Chewie 설치

dependencies:
  chewie: ^1.5.0

Chewie 예제 코드

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

class ChewieDemo extends StatefulWidget {
  @override
  _ChewieDemoState createState() => _ChewieDemoState();
}

class _ChewieDemoState extends State<ChewieDemo> {
  late VideoPlayerController _controller;
  late ChewieController _chewieController;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network(
      'https://www.example.com/sample-video.mp4',
    );
    _chewieController = ChewieController(
      videoPlayerController: _controller,
      autoPlay: true,
      looping: true,
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    _chewieController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Chewie Video Player')),
      body: Center(
        child: Chewie(controller: _chewieController),
      ),
    );
  }
}

활용 팁 및 주의사항

  1. 플랫폼 호환성
    • video_player는 Android, iOS, 웹을 지원하지만, 웹에서는 제한된 기능을 제공할 수 있습니다.
  2. 메모리 관리
    • 컨트롤러는 사용 후 반드시 dispose()를 호출하여 메모리 누수를 방지하세요.
  3. 로딩 시간 처리
    • 초기화가 완료될 때까지 로딩 인디케이터를 표시하는 것이 권장됩니다.

결론

Flutter에서 동영상 재생을 구현하려면 video_player 플러그인을 사용하여 쉽고 효율적으로 다양한 기능을 추가할 수 있습니다. 기본 기능부터 고급 UI 향상까지 모두 가능하며, 플랫폼 간 호환성과 사용자 경험을 고려한 적절한 설정이 중요합니다. 본 가이드가 Flutter 프로젝트에서 동영상 재생 기능을 구현하는 데 도움이 되길 바랍니다.

 

import 'dart:async';

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

void main() => runApp(const VideoPlayerApp());

class VideoPlayerApp extends StatelessWidget {
  const VideoPlayerApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Video Player Demo',
      home: VideoPlayerScreen(),
    );
  }
}

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

  @override
  State<VideoPlayerScreen> createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  late VideoPlayerController _controller;
  late Future<void> _initializeVideoPlayerFuture;

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

    // Create and store the VideoPlayerController. The VideoPlayerController
    // offers several different constructors to play videos from assets, files,
    // or the internet.
    _controller = VideoPlayerController.networkUrl(
      Uri.parse(
        'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
      ),
    );

    // Initialize the controller and store the Future for later use.
    _initializeVideoPlayerFuture = _controller.initialize();

    // Use the controller to loop the video.
    _controller.setLooping(true);
  }

  @override
  void dispose() {
    // Ensure disposing of the VideoPlayerController to free up resources.
    _controller.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Butterfly Video'),
      ),
      // Use a FutureBuilder to display a loading spinner while waiting for the
      // VideoPlayerController to finish initializing.
      body: FutureBuilder(
        future: _initializeVideoPlayerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            // If the VideoPlayerController has finished initialization, use
            // the data it provides to limit the aspect ratio of the video.
            return AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              // Use the VideoPlayer widget to display the video.
              child: VideoPlayer(_controller),
            );
          } else {
            // If the VideoPlayerController is still initializing, show a
            // loading spinner.
            return const Center(
              child: CircularProgressIndicator(),
            );
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Wrap the play or pause in a call to `setState`. This ensures the
          // correct icon is shown.
          setState(() {
            // If the video is playing, pause it.
            if (_controller.value.isPlaying) {
              _controller.pause();
            } else {
              // If the video is paused, play it.
              _controller.play();
            }
          });
        },
        // Display the correct icon depending on the state of the player.
        child: Icon(
          _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ),
    );
  }
}