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
相关产品推荐
相关产品推荐

