如何在Xamarin Forms中获取视频时长?
获取Xamarin中视频时长的实现方案
嘿,既然你已经搞定了视频缩略图的生成,那获取视频时长其实也是原生API就能搞定的事儿,咱们分Android和iOS两个平台来具体说:
Android平台实现
Android可以用MediaMetadataRetriever类提取视频元数据,其中就包含时长信息,代码示例如下:
using Android.Media; public static long GetVideoDuration(string videoFilePath) { // 使用using确保资源被正确释放 using (var metadataRetriever = new MediaMetadataRetriever()) { try { // 设置视频文件路径 metadataRetriever.SetDataSource(videoFilePath); // 提取时长元数据,返回的是毫秒数的字符串 string durationString = metadataRetriever.ExtractMetadata(MetadataKey.Duration); if (long.TryParse(durationString, out long durationInMilliseconds)) { // 返回毫秒数,你可以根据需求转成秒、时分秒格式 return durationInMilliseconds; } } catch (Exception ex) { // 处理异常,比如文件不存在、无权限等 Console.WriteLine($"获取视频时长失败:{ex.Message}"); } return 0; } }
注意事项
- 确保你的应用拥有读取视频文件的权限:Android 12及以下需要
READ_EXTERNAL_STORAGE权限,Android 13+需要READ_MEDIA_VIDEO权限,记得在AndroidManifest.xml中声明并动态申请权限。 - 如果视频是网络路径,
SetDataSource也支持传入URL,但需要注意网络权限和文件可访问性。
iOS平台实现
iOS则可以借助AVFoundation框架中的AVAsset来获取视频时长,代码示例如下:
using AVFoundation; using Foundation; using System.Threading.Tasks; public static async Task<double> GetVideoDurationAsync(string videoFilePath) { try { // 通过文件路径创建AVAsset实例 var videoAsset = AVAsset.FromUrl(NSUrl.FromFilename(videoFilePath)); // 异步加载时长数据 var loadStatus = await videoAsset.LoadValuesTaskAsync(new string[] { "duration" }); if (loadStatus == AVKeyValueStatus.Loaded) { // 将CMTime类型的时长转换成秒数返回 return videoAsset.Duration.Seconds; } } catch (Exception ex) { // 处理异常,比如权限不足、文件无效等 Console.WriteLine($"获取视频时长失败:{ex.Message}"); } return 0; }
注意事项
- 如果你需要访问相册中的视频,记得在Info.plist中添加
NSPhotoLibraryUsageDescription(iOS 10+)权限描述,否则会被系统拒绝访问。 AVAsset的加载是异步的,用Task处理更符合iOS的异步编程规范。
Xamarin.Forms跨平台调用
如果你是在Xamarin.Forms项目中使用,可以通过DependencyService统一调用原生实现:
- 定义共享接口:
public interface IVideoMetadataService { Task<double> GetVideoDurationAsync(string videoPath); }
- 在Android项目中实现接口:
[assembly: Dependency(typeof(VideoMetadataServiceAndroid))] namespace YourApp.Droid { public class VideoMetadataServiceAndroid : IVideoMetadataService { public Task<double> GetVideoDurationAsync(string videoPath) { long durationMs = GetVideoDuration(videoPath); // 转成秒数返回 return Task.FromResult(durationMs / 1000.0); } // 复用Android平台的时长获取方法 private long GetVideoDuration(string videoFilePath) { using (var metadataRetriever = new MediaMetadataRetriever()) { try { metadataRetriever.SetDataSource(videoFilePath); string durationString = metadataRetriever.ExtractMetadata(MetadataKey.Duration); if (long.TryParse(durationString, out long durationInMilliseconds)) { return durationInMilliseconds; } } catch (Exception ex) { Console.WriteLine($"获取视频时长失败:{ex.Message}"); } return 0; } } } }
- 在iOS项目中实现接口:
[assembly: Dependency(typeof(VideoMetadataServiceiOS))] namespace YourApp.iOS { public class VideoMetadataServiceiOS : IVideoMetadataService { public async Task<double> GetVideoDurationAsync(string videoPath) { return await GetVideoDurationInternalAsync(videoPath); } // 复用iOS平台的时长获取方法 private async Task<double> GetVideoDurationInternalAsync(string videoFilePath) { try { var videoAsset = AVAsset.FromUrl(NSUrl.FromFilename(videoFilePath)); var loadStatus = await videoAsset.LoadValuesTaskAsync(new string[] { "duration" }); if (loadStatus == AVKeyValueStatus.Loaded) { return videoAsset.Duration.Seconds; } } catch (Exception ex) { Console.WriteLine($"获取视频时长失败:{ex.Message}"); } return 0; } } }
- 在Forms项目中调用:
var durationInSeconds = await DependencyService.Get<IVideoMetadataService>().GetVideoDurationAsync("你的视频路径"); // 转成友好的时分秒格式 TimeSpan duration = TimeSpan.FromSeconds(durationInSeconds); string formattedDuration = $"{duration.Hours:D2}:{duration.Minutes:D2}:{duration.Seconds:D2}";
内容的提问来源于stack exchange,提问作者Vernon007
相关产品推荐
相关产品推荐

