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

Flutter中如何获取视频时长?不依赖video_player包的替代方法

Flutter中不依赖video_player获取视频时长的可行方案

如果不想用video_player包,你可以通过以下两种方式获取视频时长:


1. 直接通过MethodChannel调用原生系统API

这是最灵活的方案,直接利用Android和iOS自带的媒体元数据解析API,完全不依赖第三方播放器库。

Flutter端代码

import 'package:flutter/services.dart';

class VideoDurationUtil {
  static const _methodChannel = MethodChannel('video_duration_channel');

  // 返回视频时长(毫秒),失败返回null
  static Future<int?> fetchDuration(String videoPath) async {
    try {
      final int? duration = await _methodChannel.invokeMethod(
        'get_video_duration',
        {'video_path': videoPath},
      );
      return duration;
    } on PlatformException catch (e) {
      print('获取时长出错: ${e.message}');
      return null;
    }
  }
}

Android端实现(MainActivity.kt)

import android.media.MediaMetadataRetriever
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL_NAME = "video_duration_channel"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_NAME).setMethodCallHandler { call, result ->
            if (call.method == "get_video_duration") {
                val videoPath = call.argument<String>("video_path")
                if (videoPath.isNullOrEmpty()) {
                    result.error("EMPTY_PATH", "视频路径不能为空", null)
                    return@setMethodCallHandler
                }
                val retriever = MediaMetadataRetriever()
                try {
                    retriever.setDataSource(videoPath)
                    val durationStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
                    val duration = durationStr?.toLong()?.toInt()
                    result.success(duration)
                } catch (e: Exception) {
                    result.error("PARSE_FAILED", "解析视频元数据失败: ${e.message}", null)
                } finally {
                    retriever.release()
                }
            } else {
                result.notImplemented()
            }
        }
    }
}

iOS端实现(AppDelegate.swift)

import AVFoundation
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    private let CHANNEL_NAME = "video_duration_channel"

    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        guard let controller = window?.rootViewController as? FlutterViewController else {
            return super.application(application, didFinishLaunchingWithOptions: launchOptions)
        }
        let channel = FlutterMethodChannel(name: CHANNEL_NAME, binaryMessenger: controller.binaryMessenger)
        channel.setMethodCallHandler { call, result in
            if call.method == "get_video_duration" {
                guard let args = call.arguments as? [String: String],
                      let videoPath = args["video_path"],
                      let videoUrl = URL(string: videoPath) ?? URL(fileURLWithPath: videoPath) else {
                    result.error("INVALID_PATH", "无效的视频路径", null)
                    return
                }
                let asset = AVAsset(url: videoUrl)
                let durationSeconds = CMTimeGetSeconds(asset.duration)
                result.success(Int(durationSeconds * 1000))
            } else {
                result.notImplemented()
            }
        }
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

2. 使用轻量第三方库(非video_player依赖)

有些第三方库已经封装了原生的媒体元数据解析逻辑,不需要自己写MethodChannel,且不依赖video_player。比如media_info这类库:

步骤1:添加依赖

在pubspec.yaml中加入:

dependencies:
  media_info: ^2.0.0

步骤2:调用获取时长

import 'package:media_info/media_info.dart';

Future<int?> getVideoDuration(String videoPath) async {
  try {
    final mediaInfo = await MediaInfo.getMediaInfo(videoPath);
    return mediaInfo['duration'] as int?; // 返回毫秒数
  } catch (e) {
    print('获取时长失败: $e');
    return null;
  }
}

注意事项

  • 处理网络视频:原生API支持直接解析网络URL,但需要确保设备有网络权限,且视频资源支持跨域访问(iOS可能需要配置ATS)。
  • 权限问题:读取本地视频时,Android需要READ_EXTERNAL_STORAGE权限,iOS需要相册访问权限,记得在配置文件中声明。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 14:01:14