@@ -22,13 +22,24 @@ public static class MetadataService
2222 private static readonly string TMDB_API_KEY = "b5355467863d25d8a7c03c204446034c" ;
2323 private static readonly HttpClient _httpClient = new HttpClient { Timeout = TimeSpan . FromSeconds ( 10 ) } ;
2424
25+ private static bool IsEnglish ( )
26+ {
27+ if ( File . Exists ( "language.txt" ) )
28+ {
29+ string lang = File . ReadAllText ( "language.txt" ) . Trim ( ) ;
30+ if ( lang == "en" ) return true ;
31+ }
32+ return false ;
33+ }
34+
2535 public static async Task < VideoMetadata > GetMetadataAsync ( string videoFilePath )
2636 {
2737 if ( string . IsNullOrEmpty ( videoFilePath ) || ( ! File . Exists ( videoFilePath ) && ! Directory . Exists ( videoFilePath ) ) )
2838 return null ;
2939
3040 string directory = File . Exists ( videoFilePath ) ? Path . GetDirectoryName ( videoFilePath ) : videoFilePath ;
3141 string baseName = Path . GetFileNameWithoutExtension ( videoFilePath ) ;
42+ bool isEn = IsEnglish ( ) ;
3243
3344 bool isAudio = false ;
3445
@@ -50,7 +61,7 @@ public static async Task<VideoMetadata> GetMetadataAsync(string videoFilePath)
5061 if ( audioExts . Contains ( ext ) ) hasAudio = true ;
5162 if ( videoExts . Contains ( ext ) ) hasVideo = true ;
5263
53- // 性能优化:只要发现任何一个视频文件,就说明这不是纯音频专辑,立即阻断扫描
64+ // 发现任何一个视频文件立即阻断扫描
5465 if ( hasVideo ) break ;
5566 }
5667 if ( hasAudio && ! hasVideo ) isAudio = true ;
@@ -65,23 +76,26 @@ public static async Task<VideoMetadata> GetMetadataAsync(string videoFilePath)
6576
6677 if ( isAudio )
6778 {
68- var audioMeta = await Task . Run ( ( ) => GetLocalMetadata ( directory , baseName ) ) ;
79+ var audioMeta = await Task . Run ( ( ) => GetLocalMetadata ( directory , baseName , isEn ) ) ;
6980 if ( audioMeta != null )
7081 {
71- audioMeta . Genre = "音频" ;
72- audioMeta . Plot = "您选择的是本地音乐/音频文件(或专有音频文件夹),目前暂无剧情简介。" ;
82+ audioMeta . Genre = isEn ? "Audio" : "音频" ;
83+ audioMeta . Plot = isEn ? "You have selected a local audio/music file. No plot available." : "您选择的是本地音乐/音频文件(或专有音频文件夹),目前暂无剧情简介。" ;
7384 }
7485 return audioMeta ;
7586 }
7687
7788 var ( searchName , searchYear ) = CleanFileName ( baseName ) ;
7889
79- var meta = await FetchFromTmdbAsync ( searchName , searchYear , "zh-CN" ) ;
90+ string tmdbLang = isEn ? "en-US" : "zh-CN" ;
91+ var meta = await FetchFromTmdbAsync ( searchName , searchYear , tmdbLang , isEn ) ;
8092
81- // 如果没搜到,或者搜到了但是由于没中文翻译导致简介为空,自动追搜一遍英文数据
82- if ( meta == null || meta . Plot == "该剧集/电影暂无对应的简介。" )
93+ string noPlotMessage = isEn ? "No plot overview available." : "该剧集/电影暂无对应的简介。" ;
94+
95+ // 如果没搜到,或者搜到了但是中文没翻译导致简介为空(且不在英文模式下),自动追搜一遍英文数据
96+ if ( ! isEn && ( meta == null || meta . Plot == noPlotMessage ) )
8397 {
84- var enMeta = await FetchFromTmdbAsync ( searchName , searchYear , "en-US" ) ;
98+ var enMeta = await FetchFromTmdbAsync ( searchName , searchYear , "en-US" , isEn ) ;
8599 if ( enMeta != null )
86100 {
87101 if ( meta == null )
@@ -90,20 +104,20 @@ public static async Task<VideoMetadata> GetMetadataAsync(string videoFilePath)
90104 }
91105 else
92106 {
93- if ( enMeta . Plot != "该剧集/电影暂无对应的简介。 ")
107+ if ( enMeta . Plot != noPlotMessage && enMeta . Plot != "No plot overview available. ")
94108 meta . Plot = enMeta . Plot ; // 借用英文简介
95109 }
96110 }
97111 }
98112
99113 if ( meta == null )
100114 {
101- meta = await Task . Run ( ( ) => GetLocalMetadata ( directory , baseName ) ) ;
115+ meta = await Task . Run ( ( ) => GetLocalMetadata ( directory , baseName , isEn ) ) ;
102116 }
103117
104- if ( meta != null && ( string . IsNullOrEmpty ( meta . Genre ) || meta . Genre == "电影" ) )
118+ if ( meta != null && ( string . IsNullOrEmpty ( meta . Genre ) || meta . Genre == "电影" || meta . Genre == "Movie" ) )
105119 {
106- meta . Genre = "视频" ;
120+ meta . Genre = isEn ? "Video" : "视频" ;
107121 }
108122
109123 return meta ;
@@ -126,8 +140,6 @@ private static (string title, string year) CleanFileName(string fileName)
126140
127141 string [ ] tags = { "1080p" , "720p" , "2160p" , "4k" , "bluray" , "webrip" , "web-dl" , "web dl" , "hdrip" , "x264" , "x265" , "hevc" , "avc" , "aac" , "dts" , "h264" , "h265" , "10bit" , "hdr" , "ddp" , "atmos" , "truehd" , "remux" , "itunes" , "minibd" , "cmct" , "chdbits" , "yify" , "rarbg" , "tvrip" , "hdtv" } ;
128142
129-
130-
131143 foreach ( var tag in tags )
132144 {
133145 cleaned = Regex . Replace ( cleaned , $@ "\b{ tag } \b", " " , RegexOptions . IgnoreCase ) ;
@@ -148,7 +160,6 @@ private static (string title, string year) CleanFileName(string fileName)
148160 }
149161 else
150162 {
151- // 如果片名本身就是年份(如电影《1917》或《2012》),则不提取 Year 导致片名为空
152163 year = "" ;
153164 }
154165 }
@@ -162,18 +173,18 @@ private static (string title, string year) CleanFileName(string fileName)
162173 }
163174 }
164175
165- private static async Task < VideoMetadata > FetchFromTmdbAsync ( string query , string year , string language = "zh-CN" )
176+ private static async Task < VideoMetadata > FetchFromTmdbAsync ( string query , string year , string language , bool isEn )
166177 {
167178 if ( string . IsNullOrWhiteSpace ( query ) ) return null ;
168179
169- var movieMeta = await SearchTmdbCategoryAsync ( "movie" , query , year , language ) ;
180+ var movieMeta = await SearchTmdbCategoryAsync ( "movie" , query , year , language , isEn ) ;
170181 if ( movieMeta != null ) return movieMeta ;
171182
172- var tvMeta = await SearchTmdbCategoryAsync ( "tv" , query , year , language ) ;
183+ var tvMeta = await SearchTmdbCategoryAsync ( "tv" , query , year , language , isEn ) ;
173184 return tvMeta ;
174185 }
175186
176- private static async Task < VideoMetadata > SearchTmdbCategoryAsync ( string category , string query , string year , string language )
187+ private static async Task < VideoMetadata > SearchTmdbCategoryAsync ( string category , string query , string year , string language , bool isEn )
177188 {
178189 try
179190 {
@@ -197,7 +208,7 @@ private static async Task<VideoMetadata> SearchTmdbCategoryAsync(string category
197208 meta . Title = ExtractJsonString ( firstObjJson , "title" ) ?? ExtractJsonString ( firstObjJson , "name" ) ?? query ;
198209
199210 string overview = ExtractJsonString ( firstObjJson , "overview" ) ;
200- meta . Plot = ! string . IsNullOrWhiteSpace ( overview ) ? overview : " 该剧集/电影暂无对应的简介。";
211+ meta . Plot = ! string . IsNullOrWhiteSpace ( overview ) ? overview : ( isEn ? "No plot overview available." : " 该剧集/电影暂无对应的简介。") ;
201212
202213 string posterPath = ExtractJsonString ( firstObjJson , "poster_path" ) ;
203214 if ( ! string . IsNullOrEmpty ( posterPath ) )
@@ -208,7 +219,7 @@ private static async Task<VideoMetadata> SearchTmdbCategoryAsync(string category
208219 var genreIds = ExtractJsonArrayInts ( firstObjJson , "genre_ids" ) ;
209220 if ( genreIds . Count > 0 )
210221 {
211- var genres = genreIds . Select ( id => GetTmdbGenre ( id ) ) . Where ( g => g != null ) ;
222+ var genres = genreIds . Select ( id => GetTmdbGenre ( id , isEn ) ) . Where ( g => g != null ) ;
212223 meta . Genre = string . Join ( ", " , genres ) ;
213224 }
214225
@@ -247,20 +258,29 @@ private static List<int> ExtractJsonArrayInts(string json, string key)
247258 return list ;
248259 }
249260
250- private static string GetTmdbGenre ( int id )
261+ private static string GetTmdbGenre ( int id , bool isEn )
251262 {
252- var dict = new Dictionary < int , string >
263+ var dictZh = new Dictionary < int , string >
253264 {
254265 { 28 , "动作" } , { 12 , "冒险" } , { 16 , "动画" } , { 35 , "喜剧" } ,
255266 { 80 , "犯罪" } , { 99 , "纪录" } , { 18 , "剧情" } , { 10751 , "家庭" } ,
256267 { 14 , "奇幻" } , { 36 , "历史" } , { 27 , "恐怖" } , { 10402 , "音乐" } ,
257268 { 9648 , "悬疑" } , { 10749 , "爱情" } , { 878 , "科幻" } , { 10770 , "电视电影" } ,
258269 { 53 , "惊悚" } , { 10752 , "战争" } , { 37 , "西部" }
259270 } ;
271+ var dictEn = new Dictionary < int , string >
272+ {
273+ { 28 , "Action" } , { 12 , "Adventure" } , { 16 , "Animation" } , { 35 , "Comedy" } ,
274+ { 80 , "Crime" } , { 99 , "Documentary" } , { 18 , "Drama" } , { 10751 , "Family" } ,
275+ { 14 , "Fantasy" } , { 36 , "History" } , { 27 , "Horror" } , { 10402 , "Music" } ,
276+ { 9648 , "Mystery" } , { 10749 , "Romance" } , { 878 , "Science Fiction" } , { 10770 , "TV Movie" } ,
277+ { 53 , "Thriller" } , { 10752 , "War" } , { 37 , "Western" }
278+ } ;
279+ var dict = isEn ? dictEn : dictZh ;
260280 return dict . ContainsKey ( id ) ? dict [ id ] : null ;
261281 }
262282
263- private static VideoMetadata GetLocalMetadata ( string directory , string baseName )
283+ private static VideoMetadata GetLocalMetadata ( string directory , string baseName , bool isEn )
264284 {
265285 var meta = new VideoMetadata ( ) ;
266286 string [ ] possiblePosters = {
@@ -282,22 +302,22 @@ private static VideoMetadata GetLocalMetadata(string directory, string baseName)
282302 {
283303 var xdoc = XDocument . Load ( nfoPath ) ;
284304 meta . Title = xdoc . Descendants ( "title" ) . FirstOrDefault ( ) ? . Value ?? baseName ;
285- meta . Plot = xdoc . Descendants ( "plot" ) . FirstOrDefault ( ) ? . Value ?? " 无简介。";
305+ meta . Plot = xdoc . Descendants ( "plot" ) . FirstOrDefault ( ) ? . Value ?? ( isEn ? "No plot." : " 无简介。") ;
286306 var genres = xdoc . Descendants ( "genre" ) . Select ( x => x . Value ) . ToList ( ) ;
287- meta . Genre = genres . Any ( ) ? string . Join ( ", " , genres ) : " 视频";
307+ meta . Genre = genres . Any ( ) ? string . Join ( ", " , genres ) : ( isEn ? "Video" : " 视频") ;
288308 }
289309 catch
290310 {
291311 meta . Title = baseName ;
292- meta . Plot = "读取 NFO 出错。" ;
293- meta . Genre = "视频" ;
312+ meta . Plot = isEn ? "Error reading NFO." : "读取 NFO 出错。" ;
313+ meta . Genre = isEn ? "Video" : "视频" ;
294314 }
295315 }
296316 else
297317 {
298318 meta . Title = baseName ;
299- meta . Plot = "由于该视频未能自动匹配到线上数据库资料,暂无对应简介。您可以尝试修改文件名来提升匹配精度。" ;
300- meta . Genre = "视频" ;
319+ meta . Plot = isEn ? "Due to unmatched online database record, no plot is currently available. You may try modifying the filename for better matching precision." : "由于该视频未能自动匹配到线上数据库资料,暂无对应简介。您可以尝试修改文件名来提升匹配精度。" ;
320+ meta . Genre = isEn ? "Video" : "视频" ;
301321 }
302322
303323 return meta ;
0 commit comments