|
@@ -25,13 +25,22 @@ import { VipData } from '../../viewmodel/VipData';
|
|
|
import { LocalMusic } from '../../view/LocalMusic';
|
|
import { LocalMusic } from '../../view/LocalMusic';
|
|
|
import { VipPage } from '../../pages/VipPage';
|
|
import { VipPage } from '../../pages/VipPage';
|
|
|
import { FFmpeg, FFProgressMessageParser } from '@sj/ffmpeg';
|
|
import { FFmpeg, FFProgressMessageParser } from '@sj/ffmpeg';
|
|
|
|
|
+
|
|
|
interface FFMpegTags {
|
|
interface FFMpegTags {
|
|
|
album?: string;
|
|
album?: string;
|
|
|
|
|
+ ALBUM?: string;
|
|
|
artist?: string;
|
|
artist?: string;
|
|
|
|
|
+ ARTIST?: string;
|
|
|
|
|
+ TITLE?: string;
|
|
|
title?: string;
|
|
title?: string;
|
|
|
track?: string;
|
|
track?: string;
|
|
|
|
|
+ TRACK?: string;
|
|
|
TYER?: string;
|
|
TYER?: string;
|
|
|
|
|
+ year?: string;
|
|
|
|
|
+ genre?:string;
|
|
|
|
|
+ GENRE?:string;
|
|
|
date?: string;
|
|
date?: string;
|
|
|
|
|
+ DATE?: string;
|
|
|
LYRICS?: string;
|
|
LYRICS?: string;
|
|
|
lyrics?: string; // 小写变体
|
|
lyrics?: string; // 小写变体
|
|
|
USLT?: string; // ID3v2同步歌词
|
|
USLT?: string; // ID3v2同步歌词
|
|
@@ -668,6 +677,8 @@ export class Utility {
|
|
|
|
|
|
|
|
//获取音乐资源的属性值,
|
|
//获取音乐资源的属性值,
|
|
|
static async uriGetMusicAssetsFromFile(context:Context,uri:string,type:number,isLoadPixelMap?:boolean): Promise<VideoItem> {
|
|
static async uriGetMusicAssetsFromFile(context:Context,uri:string,type:number,isLoadPixelMap?:boolean): Promise<VideoItem> {
|
|
|
|
|
+ return Utility.readMetaInfoFFmpeg(context,uri,type)
|
|
|
|
|
+
|
|
|
//华为官方不支持的格式 不支持内嵌歌词Dsf,aif,aiff,wav 不支持内嵌封面dsf,aif,aiff
|
|
//华为官方不支持的格式 不支持内嵌歌词Dsf,aif,aiff,wav 不支持内嵌封面dsf,aif,aiff
|
|
|
if(StrUtil.isNotEmpty(uri)){
|
|
if(StrUtil.isNotEmpty(uri)){
|
|
|
if(uri.toLowerCase().endsWith('.dsf')
|
|
if(uri.toLowerCase().endsWith('.dsf')
|
|
@@ -881,9 +892,26 @@ export class Utility {
|
|
|
let addTime = Utility.getFormatDateStr(new Date(),'yyyy-MM-dd HH:mm');
|
|
let addTime = Utility.getFormatDateStr(new Date(),'yyyy-MM-dd HH:mm');
|
|
|
// Extract artist and title from tags
|
|
// Extract artist and title from tags
|
|
|
const tags = format.tags || {};
|
|
const tags = format.tags || {};
|
|
|
- const artist = tags.artist || '';
|
|
|
|
|
- const title = tags.title || '';
|
|
|
|
|
- const album = tags.album || '';
|
|
|
|
|
|
|
+ let artist = tags.artist ||tags.ARTIST || '';
|
|
|
|
|
+ let title = tags.title ||tags.TITLE || '';
|
|
|
|
|
+ const album = tags.album ||tags.ALBUM|| '';
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ if(StrUtil.isEmpty(title)){
|
|
|
|
|
+ //自动解析像这样的获取不到元数据的 周杰伦-七里香.mp3文件
|
|
|
|
|
+ console.log(`onecold musicName为空:${file.name}`);
|
|
|
|
|
+ const musicData = parseMusicFileName(file.name);
|
|
|
|
|
+ if (musicData.isValid) {
|
|
|
|
|
+ // console.log(`onecold 艺术家:${musicData.artist}`); // 输出:周杰伦
|
|
|
|
|
+ // console.log(`onecold 歌曲名:${musicData.title}`); // 输出:七里香
|
|
|
|
|
+ title = musicData.title
|
|
|
|
|
+ if(artist==''||artist==undefined)
|
|
|
|
|
+ artist = musicData.artist
|
|
|
|
|
+ } else {
|
|
|
|
|
+ title = file.name
|
|
|
|
|
+ // console.log("onecold 文件名格式不符合要求");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
let name: string = title;
|
|
let name: string = title;
|
|
|
if (!name) {
|
|
if (!name) {
|
|
@@ -913,9 +941,10 @@ export class Utility {
|
|
|
videoItem.probe_score = format.probe_score;
|
|
videoItem.probe_score = format.probe_score;
|
|
|
videoItem.nb_streams = format.nb_streams;
|
|
videoItem.nb_streams = format.nb_streams;
|
|
|
videoItem.nb_programs = format.nb_programs;
|
|
videoItem.nb_programs = format.nb_programs;
|
|
|
- videoItem.year = tags.TYER || tags.date || 'unknown'; // try different tag names for year
|
|
|
|
|
|
|
+ videoItem.year = tags.TYER || tags.date ||tags.DATE|| 'unknown'; // try different tag names for year
|
|
|
videoItem.lyricContent = tags.LYRICS || tags.lyrics || tags.USLT || tags.UNSYNCEDLYRICS || '';
|
|
videoItem.lyricContent = tags.LYRICS || tags.lyrics || tags.USLT || tags.UNSYNCEDLYRICS || '';
|
|
|
-
|
|
|
|
|
|
|
+ videoItem.genre = tags.genre||tags.GENRE||'unknown';
|
|
|
|
|
+ videoItem.track = tags.track||tags.TRACK||'';
|
|
|
// 检查是否有封面图片流
|
|
// 检查是否有封面图片流
|
|
|
const hasCover = metadata.streams.some(stream =>
|
|
const hasCover = metadata.streams.some(stream =>
|
|
|
stream.disposition?.attached_pic === 1
|
|
stream.disposition?.attached_pic === 1
|
|
@@ -926,18 +955,13 @@ export class Utility {
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
let md5Name = await MD5.digestSync(inputPath)
|
|
let md5Name = await MD5.digestSync(inputPath)
|
|
|
- // const imageName = `${md5Name}.jpg`;
|
|
|
|
|
- const imagePath = `${context.filesDir}${FileUtil.separator}${md5Name}`;
|
|
|
|
|
|
|
+ let imagePath = `${context.filesDir}${FileUtil.separator}${md5Name}.jpg`;
|
|
|
console.info('readMetaInfoFFmpeg asset imagePath: ', imagePath);
|
|
console.info('readMetaInfoFFmpeg asset imagePath: ', imagePath);
|
|
|
- // 提取封面图片
|
|
|
|
|
- // await extractCoverImage(inputPath, imagePath);
|
|
|
|
|
- await FFmpegCover(inputPath, imagePath);
|
|
|
|
|
-
|
|
|
|
|
- // 检查图片是否生成成功
|
|
|
|
|
- if (fs.accessSync(imagePath)) {
|
|
|
|
|
- videoItem.pixelMapPath = imagePath;
|
|
|
|
|
|
|
+ //提取封面
|
|
|
|
|
+ await getFFmpegCover(inputPath, imagePath);
|
|
|
|
|
+ imagePath = fileUri.getUriFromPath(imagePath)
|
|
|
|
|
+ videoItem.pixelMapPath = imagePath;
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.warn(' 提取封面图片失败:', error.message);
|
|
console.warn(' 提取封面图片失败:', error.message);
|
|
|
}
|
|
}
|
|
@@ -1601,7 +1625,7 @@ function getFileNameWithoutExtension(filePath: string): string {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 从音乐文件中提取封面
|
|
|
|
|
|
|
+ * 从视频文件中提取封面
|
|
|
* @param inputPath 音乐文件路径
|
|
* @param inputPath 音乐文件路径
|
|
|
* @returns Promise<void>
|
|
* @returns Promise<void>
|
|
|
*/
|
|
*/
|
|
@@ -1635,8 +1659,8 @@ async function extractCoverImage(inputPath: string, outputPath: string): Promise
|
|
|
* @param inputPath 音乐文件路径
|
|
* @param inputPath 音乐文件路径
|
|
|
* @returns Promise<void>
|
|
* @returns Promise<void>
|
|
|
*/
|
|
*/
|
|
|
-async function FFmpegCover(inputPath: string, outputPath: string) {
|
|
|
|
|
- let commands = ["ffmpeg", "-i", inputPath, "-map", "0:v", "-c:v", "copy", outputPath];
|
|
|
|
|
|
|
+async function getFFmpegCover(inputPath: string, outputPath: string) {
|
|
|
|
|
+ let commands = ["ffmpeg", "-y","-i", inputPath, "-map", "0:v", "-c:v", "copy", outputPath];
|
|
|
FFmpeg.execute(commands, {
|
|
FFmpeg.execute(commands, {
|
|
|
logCallback: (logLevel: number, logMessage: string) => {
|
|
logCallback: (logLevel: number, logMessage: string) => {
|
|
|
console.info(`[FFmpeg LOG] [${logLevel}]${logMessage}`)
|
|
console.info(`[FFmpeg LOG] [${logLevel}]${logMessage}`)
|