You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter应用中基于TMDB API实现视频播放功能?

基于TMDB API的Flutter应用视频播放实现方案

我正在用TMDB(The Movie Database)API开发Flutter应用,现在在实现视频播放功能时遇到了困难,想要合适的代码方案来添加这个功能。下面是我的API响应和现有代码:

API响应

API响应截图

现有代码

class upcoming_detail extends StatefulWidget {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        centerTitle: true,
        backgroundColor: Colors.grey,
      ),
      body: Column(
        children: [
          Stack(
            children: [
              Container(
                width: double.infinity,
                height: 300,
                decoration: BoxDecoration(
                  image: DecorationImage(
                    fit: BoxFit.cover,
                    image: NetworkImage(
                      "https://image.tmdb.org/t/p/w500${widget.image}",
                    ),
                  ),
                ),
              ),
              Positioned.fill(
                child: Align(
                  alignment: Alignment.center,
                  child: IconButton(
                    icon: Icon(
                      Icons.play_circle_fill,
                      size: 70,
                      color: Colors.white,
                    ),
                    onPressed: () {

                      // handle video play action
                    },
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
    );

实现方案

TMDB返回的视频大多托管在YouTube,推荐使用youtube_player_flutter插件快速实现播放,以下是完整步骤:

1. 添加依赖

在pubspec.yaml中添加所需依赖:

dependencies:
  flutter:
    sdk: flutter
  youtube_player_flutter: ^8.1.2
  http: ^1.1.0

执行flutter pub get完成依赖安装。

2. 完善页面代码

需要传递电影ID获取视频数据,同时实现播放按钮的跳转逻辑:

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';

class upcoming_detail extends StatefulWidget {
  final String title;
  final String image;
  final int movieId; // 新增:传递电影ID用于获取视频

  const upcoming_detail({
    Key? key,
    required this.title,
    required this.image,
    required this.movieId,
  }) : super(key: key);

  @override
  State<upcoming_detail> createState() => _upcoming_detailState();
}

class _upcoming_detailState extends State<upcoming_detail> {
  String? _videoKey; // 存储YouTube视频ID

  @override
  void initState() {
    super.initState();
    _fetchMovieVideos(); // 页面初始化时获取视频数据
  }

  // 从TMDB API获取视频列表
  Future<void> _fetchMovieVideos() async {
    const apiKey = "YOUR_TMDB_API_KEY"; // 替换为你的TMDB API密钥
    final url = Uri.parse(
      "https://api.themoviedb.org/3/movie/${widget.movieId}/videos?api_key=$apiKey&language=en-US",
    );

    final response = await http.get(url);
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      final videos = data["results"] as List;
      if (videos.isNotEmpty) {
        // 取第一个视频(通常是官方预告片)
        setState(() {
          _videoKey = videos[0]["key"];
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        centerTitle: true,
        backgroundColor: Colors.grey,
      ),
      body: Column(
        children: [
          Stack(
            children: [
              Container(
                width: double.infinity,
                height: 300,
                decoration: BoxDecoration(
                  image: DecorationImage(
                    fit: BoxFit.cover,
                    image: NetworkImage(
                      "https://image.tmdb.org/t/p/w500${widget.image}",
                    ),
                  ),
                ),
              ),
              Positioned.fill(
                child: Align(
                  alignment: Alignment.center,
                  child: IconButton(
                    icon: const Icon(
                      Icons.play_circle_fill,
                      size: 70,
                      color: Colors.white,
                    ),
                    onPressed: _videoKey != null
                        ? () {
                            // 跳转到视频播放页面
                            Navigator.push(
                              context,
                              MaterialPageRoute(
                                builder: (_) => VideoPlayerPage(videoKey: _videoKey!),
                              ),
                            );
                          }
                        : null, // 没有视频时禁用按钮
                  ),
                ),
              ),
            ],
          ),
          // 可添加其他电影详情内容
        ],
      ),
    );
  }
}

// 独立的视频播放页面
class VideoPlayerPage extends StatelessWidget {
  final String videoKey;

  const VideoPlayerPage({Key? key, required this.videoKey}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final playerController = YoutubePlayerController(
      initialVideoId: videoKey,
      flags: const YoutubePlayerFlags(
        autoPlay: true,
        mute: false,
        enableCaption: true,
      ),
    );

    return Scaffold(
      appBar: AppBar(title: const Text("播放视频")),
      body: YoutubePlayer(
        controller: playerController,
        showVideoProgressIndicator: true,
        progressIndicatorColor: Colors.blueAccent,
        onReady: () => playerController.play(),
      ),
    );
  }
}

3. 关键注意事项

  • 替换代码中的YOUR_TMDB_API_KEY为你自己的TMDB密钥
  • Android平台需在AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET"/>
  • iOS平台需在Info.plist中添加:
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    
  • 如果需要支持非YouTube的视频源,可以使用video_player插件,需获取视频的直接流媒体URL,TMDB部分视频可能提供其他平台的源,需额外判断site字段处理。

内容的提问来源于stack exchange,提问作者Muhammad Zohaib

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 01:52:55