使用getAsset()和getThumbnail()方法需要申请受限开放权限'ohos.permission.READ_IMAGEVIDEO',对于需要克隆、备份或同步图片/视频类文件的应用可申请获取该权限,并通过getAlbums()方法获取相册资源再调用这两个方法获取缩略图。或者通过picker的方式可以在不获取权限的情况下,使用这两个方法来访问用户指定的图库资源获取缩略图。本文中的示例使用的是第二种picker的方式。
视频缩略图是视频的静态预览图像,是从视频中截取的某一帧画面,经常用作视频的封面。在视频浏览、分享和管理等场景中使用可以帮助用户快速浏览和选择想要的内容,提高用户的使用体验。HarmonyOS提供了对应的模块能力,帮助开发者获取视频文件的缩略图。根据应用获取缩略图策略的不同,可以分为以下两种场景:
视频的默认缩略图一般为视频的第一帧,可以通过PhotoAsset类的getThumbnail()方法获取。这里以获取图库视频缩略图场景为例。
//src/main/ets/common/utils/PhotoUtils.ets /** * Pull up the gallery picker and select a video. * @returns The url of the selected video. */ async selectVideo(): Promise<string> { let photoViewPicker = new photoAccessHelper.PhotoViewPicker(); return photoViewPicker.select({ MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE, maxSelectNumber: 1 }).then((photoSelectResult: photoAccessHelper.PhotoSelectResult): string => { if (photoSelectResult.photoUris.length <= 0) { return ''; } return photoSelectResult.photoUris[0]; }) }
//src/main/ets/common/utils/PhotoUtils.ets // Obtain video resources. let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates(); predicates.equalTo('uri', videoUrl); let videoFetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await this.phAccessHelper.getAssets({ fetchColumns: ['width', 'height', 'orientation'], predicates: predicates }); let photoAsset: photoAccessHelper.PhotoAsset = await videoFetchResult.getFirstObject();
//src/main/ets/common/utils/PhotoUtils.ets // Configure thumbnail parameters. let thumbnailSize: Size = { width: 0, height: 0 }; if (photoAsset.get(photoAccessHelper.PhotoKeys.ORIENTATION) === 90 || photoAsset.get(photoAccessHelper.PhotoKeys.ORIENTATION) === 270) { thumbnailSize.width = photoAsset.get(photoAccessHelper.PhotoKeys.HEIGHT) as number; thumbnailSize.height = photoAsset.get(photoAccessHelper.PhotoKeys.WIDTH) as number; } else { thumbnailSize.width = photoAsset.get(photoAccessHelper.PhotoKeys.WIDTH) as number; thumbnailSize.height = photoAsset.get(photoAccessHelper.PhotoKeys.HEIGHT) as number; } return photoAsset.getThumbnail(thumbnailSize);
使用getAsset()和getThumbnail()方法需要申请受限开放权限'ohos.permission.READ_IMAGEVIDEO',对于需要克隆、备份或同步图片/视频类文件的应用可申请获取该权限,并通过getAlbums()方法获取相册资源再调用这两个方法获取缩略图。或者通过picker的方式可以在不获取权限的情况下,使用这两个方法来访问用户指定的图库资源获取缩略图。本文中的示例使用的是第二种picker的方式。
HarmonyOS提供视频缩略图获取类AVImageGenerator用于选取视频指定时间的帧作为缩略图,这里以选取图库视频缩略图场景为例。
//src/main/ets/pages/Index.ets /** * Obtain video resources through AVImageGenerator. */ async imageGeneratorGetThumbnail() { this.photoUtils.selectVideo().then(async (result: string) => { // ... this.fileAlbum = fileIo.openSync(result, fileIo.OpenMode.READ_ONLY); this.avFileDescriptor = { fd: this.fileAlbum.fd }; // ... } ).catch((error: BusinessError) => { hilog.error(0x0000, TAG, `Invoke imageGeneratorGetThumbnail failed!, error code: ${error.code}, message: ${error.message}`); }) }
//src/main/ets/common/utils/PhotoUtils.ets /** * Get video infos through video file descriptor. * @param avFileDescriptor AVFileDescriptor of video. * @returns the size infos of video. */ async getVideoData(avFileDescriptor: media.AVFileDescriptor): Promise<VideoSizeData> { let videoSize: VideoSizeData = new VideoSizeData(); let avMetaDataExtractor: media.AVMetadataExtractor = await media.createAVMetadataExtractor(); avMetaDataExtractor.fdSrc = avFileDescriptor; let metadata = await avMetaDataExtractor.fetchMetadata(); videoSize.photoSize.width = parseInt(metadata.videoWidth as string); videoSize.photoSize.height = parseInt(metadata.videoHeight as string); if (metadata.duration) { videoSize.totalTime = parseInt(metadata.duration); } avMetaDataExtractor.release(); return videoSize; }
//src/main/ets/pages/Index.ets this.avImageGenerator = await media.createAVImageGenerator(); if (this.avImageGenerator) { this.avImageGenerator.fdSrc = this.avFileDescriptor; } else { hilog.error(0X0000, TAG, 'Create AVImageGenerator failed!'); return; }
//src/main/ets/pages/Index.ets /** * Obtain a frame at a certain point in time of the video. * @param time A certain point in time of the video. */ async fetchFrameByTime(time: number) { this.pixelMap = await this.avImageGenerator?.fetchFrameByTime(time, media.AVImageQueryOptions.AV_IMAGE_QUERY_CLOSEST_SYNC, this.videoSize.photoSize); }