Przeglądaj źródła

实现导入的如果是视频,获取视频封面

onecold 1 rok temu
rodzic
commit
e85dce5779

+ 36 - 99
entry/src/main/ets/common/util/Utility.ets

@@ -529,67 +529,9 @@ export class Utility {
 
     return format;
   }
-  //获取从文件管理器获得的视频资源的属性值
-  static async uriGetAssetsFromFile(context:Context,uri:string,type:number,isLoadPixelMap?:boolean): Promise<VideoItem> {
-    let item:VideoItem = new VideoItem('',uri,uri,type,0,'')
-    try {
-      console.info('asset file.uri: ', uri);
-
-
-      let file = fs.openSync(uri, fs.OpenMode.READ_ONLY | fs.OpenMode.CREATE)
-      console.info("file.fd " + file.fd);
-      let fdfd = 'fd://' + file.fd
-      //3、通过fs.stat方法获取stat对象
-      console.info('asset file.name: ', file.name);
-      console.info('asset file.uri: ', uri);
-      console.info('asset file.fd: ', file.fd);
-      console.info('asset file.path: ', file.path);
-      item = new VideoItem(file.name,uri,uri,type,0,'')
-      await fs.stat(file.fd).then(async (stat: fs.Stat) => {
-        console.info("get file info succeed, the size of file is " + stat.size);
-        let videoSize =  stat.size
-        // let videoTime = stat.ctime
-
-        let fileSize = Utility.formatFSize(videoSize)
-        let cTime = Utility.getFormatDateStr(stat.mtime,'yyyy-MM-dd HH:mm')
-
-        // console.info('asset stat.ino: ', stat.ino);
-        // console.info('asset stat.mode: ', stat.mode);
-        // console.info('asset stat.uid: ', stat.uid);
-        // console.info('asset stat.ino: ', stat.gid);
-        // console.info('asset stat.size: ', stat.size);
-        console.info('asset stat.ctime: ', stat.ctime);
-        // console.info('asset stat.mtime: ', stat.mtime);
-        // console.info('asset stat.duration: ', duration);
-
-
-        let pixelMap:image.PixelMap|undefined = undefined
-        if(isLoadPixelMap){
-          //获取缩略图
-          if(Utility.isVideoByExtension(uri)){
-            pixelMap = await Utility.getFetchFrameByTime(uri)
-          }else{
-            pixelMap = await Utility.getFetchMetadataFromFdSrcByPromise(uri)
-          }
-        }
-
-        item = new VideoItem( file.name,uri ,uri,type,videoSize,cTime,pixelMap,fileSize,
-          await ImageUtil.pixelMapToBase64Str(pixelMap))
-
 
 
 
-      })
-    } catch (error) {
-      console.error('uriGetAssetsFromFile failed with err: ' + JSON.stringify(error));
-    }
-
-    return item
-
-
-  }
-
-
   static async getFilePixelMapBig(uri:string){
     let pixelMap:image.PixelMap|undefined = undefined
     if(Utility.isMusicByExtension(uri)){
@@ -954,23 +896,25 @@ export class Utility {
             stream.disposition?.attached_pic  === 1
             );
             console.info('readMetaInfoFFmpeg asset hasCover: ', hasCover);
+            let md5Name = await MD5.digestSync(inputPath)
+            let imagePath = `${context.filesDir}${FileUtil.separator}${md5Name}.jpg`;
+            console.info('readMetaInfoFFmpeg asset imagePath: ', imagePath);
             // 如果有封面图片,则提取
-            if (hasCover) {
-
-              try {
-                let md5Name = await MD5.digestSync(inputPath)
-                let imagePath = `${context.filesDir}${FileUtil.separator}${md5Name}.jpg`;
-                console.info('readMetaInfoFFmpeg asset imagePath: ', imagePath);
+            try {
+              if (hasCover) {
+                  //提取封面
+                  await getFFmpegCover(inputPath, imagePath);
+                  imagePath = fileUri.getUriFromPath(imagePath)
+                  videoItem.pixelMapPath  = imagePath;
+              }else if(Utility.isVideoByExtension(inputPath)){
                 //提取封面
-                await getFFmpegCover(inputPath, imagePath);
+                await getVideoFFmpegCover(inputPath, imagePath);
                 imagePath = fileUri.getUriFromPath(imagePath)
                 videoItem.pixelMapPath  = imagePath;
-
-              } catch (error) {
-                console.warn(' 提取封面图片失败:', error.message);
               }
+            } catch (error) {
+              console.warn(' 提取封面图片失败:', error.message);
             }
-
             console.info('Successfully  parsed metadata:', videoItem);
             resolve(videoItem);
           })
@@ -1628,35 +1572,6 @@ function getFileNameWithoutExtension(filePath: string): string {
   return lastDotIndex > 0 ? fileName.substring(0,  lastDotIndex) : fileName;
 }
 
-/**
- * 从视频文件中提取封面
- * @param inputPath 音乐文件路径
- * @returns Promise<void>
- */
-async function extractCoverImage(inputPath: string, outputPath: string): Promise<void> {
-  const commands = [
-    'ffmpeg',
-    '-i', inputPath,
-    '-an',              // 禁用音频
-    '-vcodec', 'copy',  // 直接复制视频流
-    '-f', 'image2',     // 强制输出为图片
-    '-y',               // 覆盖输出文件
-    outputPath
-  ];
-
-  return new Promise((resolve, reject) => {
-    FFmpeg.execute(commands,  {
-      logCallback: (logLevel: number, logMessage: string) => {
-        console.log(`[${logLevel}]${logMessage}`);
-      },
-      outputCallback: (message: string) => {
-        console.log(`FFmpeg  output: ${message}`);
-      },
-    }).then(() => resolve())
-      .catch((error: BusinessError) => reject(error));
-  });
-}
-
 
 /**
  * 从音乐文件中提取封面
@@ -1680,6 +1595,28 @@ async function getFFmpegCover(inputPath: string, outputPath: string) {
       console.error(`FFmpeg execution failed with error: ${error.message}`);
     });
 }
+/**
+ * 从视频文件中提取封面 提前视频第5帧的封面
+ * @param inputPath 文件路径
+ * @returns Promise<void>
+ */
+async function getVideoFFmpegCover(inputPath: string, outputPath: string) {
+  let commands = ["ffmpeg", "-y","-i", inputPath, "-ss", "00:00:05", "-t", "1","-r",'1','-q:v','2','-f','image2', outputPath];
+  FFmpeg.execute(commands, {
+    logCallback: (logLevel: number, logMessage: string) => {
+      console.info(`[FFmpegX LOG] [${logLevel}]${logMessage}`)
+    },
+    progressCallback: (message: string) => {
+      console.info(`[FFmpegX progress]${JSON.stringify(FFProgressMessageParser.parse(message))}`)
+    },
+  })
+    .then(() => {
+
+    })
+    .catch((error: Error) => {
+      console.error(`FFmpegX execution failed with error: ${error.message}`);
+    });
+}
 
 /**
  * 从音乐文件中提取歌词内容
@@ -1825,7 +1762,7 @@ interface SupportedFormats {
 // 声明并初始化支持的音频格式(符合类型定义)
 const SUPPORTED_FORMATS: SupportedFormats = {
   LOSSY: new Set(['mp3', 'aac', 'ogg', 'opus', 'wma']),
-  LOSSLESS: new Set(['flac', 'alac', 'ape', 'wav', 'aiff'])
+  LOSSLESS: new Set(['flac', 'alac', 'ape', 'wav', 'aiff', 'dsf','aif'])
 };
 
 /**

+ 1 - 1
entry/src/main/ets/pages/ScanFilePage.ets

@@ -244,7 +244,7 @@ export struct ScanFilePage{
             })
             .alignSelf(ItemAlign.Center)
             .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
-              .animation({ duration: 380, curve: Curve.Ease,delay:40 }))
+              .animation({ duration: 380, curve: Curve.Ease,delay:30 }))
 
           Column() {
             Row() {

+ 3 - 3
entry/src/main/ets/view/LocalMusic.ets

@@ -3629,7 +3629,7 @@ export struct LocalMusic {
                 .margin({ top: 2 ,right:6})
                 .visibility((this.modeType == 3 && !this.isCanBack)||(this.modeType == 2 && !this.isCanBack)
                      ||(this.modeType == 0&&item.type==CommonConstants.TYPE_IS_DIR)? Visibility.None : Visibility.Visible)
-                Text(StrUtil.isEmpty(item.artist) ? 'Unknown' : item.artist)
+                Text(StrUtil.isEmpty(item.artist) ? item.duration: item.artist)
                   .fontSize(11)
                   .fontSize(this.twoFingerType == 1 ? 10 : this.twoFingerType == 2 ? 12 : 14)
                   .maxLines(1)
@@ -5725,7 +5725,7 @@ export struct LocalMusic {
                   $r('app.color.text_color'))
                   .fontWeight(500)
                   .borderRadius(12)
-                  .margin({ left: this.twoFingerType == 3 ? 6 : 8 })
+                  .margin({ left: this.twoFingerType == 3 ? 12 : 10 })
                   .backgroundColor('#FFC107')
               }
               .padding({ top: 8 })
@@ -5734,7 +5734,7 @@ export struct LocalMusic {
                 .padding({ top: 8 })
                 .fontColor(this.curIndex === index ? this.themeColor :
                   this.isFrontWhite ? $r('app.color.playlistText_color') : $r('app.color.text_color'))
-                .margin({ left: this.twoFingerType == 3 ? 18 : 10 })
+                .margin({ left: this.twoFingerType == 3 ? 5 : 3 })
               Blank()
               Text(item.size)
                 .fontSize(this.twoFingerType == 1 ? 11 : this.twoFingerType == 2 ? 12 : 14)