下载音频时,可能不是mp3 可能是m4a格式,暂时就遇到这2种

ffmpeg命令优化
This commit is contained in:
jianzhichu
2026-01-08 00:23:08 +08:00
parent 4e0169da90
commit 1006de4a0d
8 changed files with 226 additions and 94 deletions
@@ -3,7 +3,7 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<_PublishTargetUrl>E:\code\dysync\bin\Release\net6.0\publish\</_PublishTargetUrl> <_PublishTargetUrl>E:\code\dysync\bin\Release\net6.0\publish\</_PublishTargetUrl>
<History>True|2026-01-03T13:38:51.4307034Z||;True|2026-01-02T19:09:16.9668906+08:00||;False|2026-01-02T19:09:11.7496369+08:00||;True|2026-01-02T15:42:08.2215697+08:00||;True|2026-01-02T09:46:56.1654861+08:00||;True|2026-01-02T09:35:28.0211225+08:00||;True|2026-01-01T23:07:01.9022045+08:00||;False|2026-01-01T23:06:56.0537216+08:00||;True|2026-01-01T22:16:10.2974067+08:00||;True|2026-01-01T22:16:06.2123787+08:00||;False|2026-01-01T22:15:33.3626979+08:00||;True|2026-01-01T22:01:30.7161900+08:00||;True|2026-01-01T21:10:19.3664263+08:00||;True|2026-01-01T21:09:38.6071080+08:00||;True|2025-12-30T11:45:54.5543034+08:00||;True|2025-12-30T09:19:08.3178124+08:00||;True|2025-12-29T18:57:29.7032246+08:00||;True|2025-12-27T14:52:24.4780776+08:00||;False|2025-12-27T14:52:19.5635794+08:00||;True|2025-12-27T14:48:01.6252748+08:00||;False|2025-12-27T14:47:55.7976192+08:00||;True|2025-12-27T14:38:23.9723838+08:00||;True|2025-12-27T13:00:29.8583858+08:00||;True|2025-12-26T22:18:42.4015637+08:00||;True|2025-12-26T22:10:58.5274572+08:00||;True|2025-12-26T22:06:26.3129600+08:00||;True|2025-12-26T22:03:55.6718618+08:00||;False|2025-12-26T22:03:48.3809954+08:00||;True|2025-12-26T22:02:33.1840390+08:00||;True|2025-12-26T22:01:16.1660100+08:00||;True|2025-12-25T00:50:26.1116465+08:00||;True|2025-12-25T00:48:27.3087708+08:00||;True|2025-12-25T00:47:38.4835720+08:00||;</History> <History>True|2026-01-07T16:16:24.4451490Z||;True|2026-01-08T00:14:20.7430793+08:00||;True|2026-01-08T00:07:46.7228194+08:00||;True|2026-01-07T23:52:13.3290082+08:00||;True|2026-01-07T23:49:28.4838650+08:00||;True|2026-01-07T23:47:45.1936189+08:00||;True|2026-01-07T23:35:09.7818611+08:00||;True|2026-01-07T23:20:43.7462863+08:00||;True|2026-01-07T23:04:39.5140429+08:00||;False|2026-01-07T23:04:36.5367611+08:00||;True|2026-01-07T22:53:14.6013449+08:00||;True|2026-01-07T22:49:59.9549006+08:00||;True|2026-01-07T22:36:40.0254856+08:00||;False|2026-01-07T22:36:28.8275903+08:00||;True|2026-01-07T21:59:51.4355171+08:00||;True|2026-01-03T21:38:51.4307034+08:00||;True|2026-01-02T19:09:16.9668906+08:00||;False|2026-01-02T19:09:11.7496369+08:00||;True|2026-01-02T15:42:08.2215697+08:00||;True|2026-01-02T09:46:56.1654861+08:00||;True|2026-01-02T09:35:28.0211225+08:00||;True|2026-01-01T23:07:01.9022045+08:00||;False|2026-01-01T23:06:56.0537216+08:00||;True|2026-01-01T22:16:10.2974067+08:00||;True|2026-01-01T22:16:06.2123787+08:00||;False|2026-01-01T22:15:33.3626979+08:00||;True|2026-01-01T22:01:30.7161900+08:00||;True|2026-01-01T21:10:19.3664263+08:00||;True|2026-01-01T21:09:38.6071080+08:00||;True|2025-12-30T11:45:54.5543034+08:00||;True|2025-12-30T09:19:08.3178124+08:00||;True|2025-12-29T18:57:29.7032246+08:00||;True|2025-12-27T14:52:24.4780776+08:00||;False|2025-12-27T14:52:19.5635794+08:00||;True|2025-12-27T14:48:01.6252748+08:00||;False|2025-12-27T14:47:55.7976192+08:00||;True|2025-12-27T14:38:23.9723838+08:00||;True|2025-12-27T13:00:29.8583858+08:00||;True|2025-12-26T22:18:42.4015637+08:00||;True|2025-12-26T22:10:58.5274572+08:00||;True|2025-12-26T22:06:26.3129600+08:00||;True|2025-12-26T22:03:55.6718618+08:00||;False|2025-12-26T22:03:48.3809954+08:00||;True|2025-12-26T22:02:33.1840390+08:00||;True|2025-12-26T22:01:16.1660100+08:00||;True|2025-12-25T00:50:26.1116465+08:00||;True|2025-12-25T00:48:27.3087708+08:00||;True|2025-12-25T00:47:38.4835720+08:00||;</History>
<LastFailureDetails /> <LastFailureDetails />
</PropertyGroup> </PropertyGroup>
</Project> </Project>
+1 -1
View File
@@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<_PublishTargetUrl>E:\code\dysync\bin\Release\net6.0\publish\</_PublishTargetUrl> <_PublishTargetUrl>E:\code\dysync\bin\Release\net6.0\publish\</_PublishTargetUrl>
<History>True|2026-01-03T13:42:41.3864639Z||;False|2026-01-03T21:42:26.7041325+08:00||;True|2026-01-02T09:32:11.1396877+08:00||;True|2026-01-01T23:30:38.0205783+08:00||;True|2026-01-01T23:29:35.2877898+08:00||;False|2026-01-01T23:27:39.5930556+08:00||;False|2026-01-01T23:24:52.0996222+08:00||;False|2026-01-01T23:24:09.0444840+08:00||;False|2026-01-01T23:24:06.1610789+08:00||;False|2026-01-01T23:24:03.3178410+08:00||;False|2026-01-01T23:22:56.2224992+08:00||;False|2026-01-01T23:22:47.8246988+08:00||;False|2026-01-01T23:22:43.2890820+08:00||;True|2026-01-01T23:21:03.6027351+08:00||;True|2026-01-01T23:07:57.5938094+08:00||;True|2025-12-29T18:55:45.8262096+08:00||;True|2025-12-28T00:21:04.1648410+08:00||;True|2025-12-28T00:18:49.2137559+08:00||;True|2025-12-28T00:14:18.1456892+08:00||;True|2025-12-28T00:11:06.6645248+08:00||;False|2025-12-28T00:10:49.4906020+08:00||;True|2025-12-27T23:51:57.6426264+08:00||;True|2025-12-27T23:40:08.4783210+08:00||;True|2025-12-27T14:59:32.0605406+08:00||;False|2025-12-27T14:59:21.2076690+08:00||;True|2025-12-27T12:58:06.9934830+08:00||;True|2025-12-27T12:51:45.3402320+08:00||;True|2025-12-27T12:45:49.9795040+08:00||;True|2025-12-27T12:42:13.9395619+08:00||;True|2025-12-27T11:32:35.8851241+08:00||;True|2025-12-27T11:32:11.1199261+08:00||;True|2025-12-27T11:31:34.3939619+08:00||;True|2025-12-26T22:39:54.4903900+08:00||;False|2025-12-26T22:39:38.9956198+08:00||;True|2025-12-26T13:29:16.3817938+08:00||;True|2025-12-26T13:13:27.1756564+08:00||;True|2025-12-26T13:12:27.5681845+08:00||;True|2025-12-25T21:53:39.9851108+08:00||;True|2025-12-25T21:14:06.5238213+08:00||;True|2025-12-25T14:05:40.5153425+08:00||;True|2025-12-25T00:52:42.0632072+08:00||;False|2025-12-25T00:52:36.5033522+08:00||;True|2025-12-24T20:47:03.4244585+08:00||;True|2025-12-24T20:38:49.1905853+08:00||;True|2025-12-24T20:38:18.7336590+08:00||;True|2025-12-24T20:33:27.1126773+08:00||;True|2025-12-24T20:32:29.2799273+08:00||;True|2025-12-23T20:55:43.6793723+08:00||;True|2025-12-23T20:54:55.9960612+08:00||;True|2025-12-21T13:23:11.0272294+08:00||;True|2025-12-21T13:22:56.8339811+08:00||;False|2025-12-21T13:22:50.2395530+08:00||;True|2025-12-21T13:11:36.6129339+08:00||;True|2025-12-21T12:15:18.4086793+08:00||;True|2025-12-21T12:15:11.4448190+08:00||;True|2025-12-20T14:05:36.6224332+08:00||;False|2025-12-20T14:05:28.6359828+08:00||;True|2025-12-20T13:58:30.1641630+08:00||;True|2025-12-20T13:55:16.1759645+08:00||;True|2025-12-20T12:16:22.5224516+08:00||;True|2025-12-19T09:50:16.9517676+08:00||;True|2025-12-19T09:49:47.0871734+08:00||;False|2025-12-19T09:49:36.7638757+08:00||;True|2025-12-19T09:35:13.2489248+08:00||;True|2025-12-14T19:09:59.9031104+08:00||;True|2025-12-13T21:21:10.0022707+08:00||;True|2025-12-11T22:07:16.6229994+08:00||;True|2025-12-11T22:05:56.7363206+08:00||;True|2025-12-11T22:01:07.5862406+08:00||;True|2025-12-11T22:00:43.5796594+08:00||;True|2025-12-08T21:20:37.8369271+08:00||;False|2025-12-08T21:20:21.1646252+08:00||;True|2025-12-08T20:51:50.6845619+08:00||;True|2025-12-08T16:43:45.2425324+08:00||;False|2025-12-08T16:42:23.0308163+08:00||;True|2025-12-08T16:41:52.4103868+08:00||;True|2025-12-08T16:41:49.8972006+08:00||;False|2025-12-08T16:41:39.5343442+08:00||;True|2025-12-08T12:40:19.2430740+08:00||;True|2025-12-08T12:02:30.6005542+08:00||;True|2025-12-08T11:34:29.6673185+08:00||;False|2025-12-08T11:30:56.2857042+08:00||;True|2025-12-08T10:52:43.7427594+08:00||;True|2025-12-08T07:05:03.2845531+08:00||;True|2025-12-07T23:02:10.0037815+08:00||;True|2025-12-07T22:48:25.7859648+08:00||;True|2025-12-07T20:49:13.6683281+08:00||;True|2025-12-07T08:47:30.1236366+08:00||;True|2025-12-06T13:14:32.4410202+08:00||;True|2025-12-06T13:07:29.7182102+08:00||;True|2025-12-06T13:05:46.2855366+08:00||;False|2025-12-06T13:05:40.3550904+08:00||;True|2025-12-06T13:03:47.8773880+08:00||;True|2025-12-06T13:03:28.9521030+08:00||;True|2025-12-05T23:11:51.5026151+08:00||;True|2025-12-05T12:46:26.1415079+08:00||;False|2025-12-05T12:46:19.1274332+08:00||;True|2025-12-05T09:04:36.7111717+08:00||;True|2025-12-05T08:22:51.7343317+08:00||;True|2025-12-05T08:20:32.0383739+08:00||;</History> <History>True|2026-01-07T16:19:20.8948701Z||;True|2026-01-07T21:59:04.8702022+08:00||;True|2026-01-03T21:42:41.3864639+08:00||;False|2026-01-03T21:42:26.7041325+08:00||;True|2026-01-02T09:32:11.1396877+08:00||;True|2026-01-01T23:30:38.0205783+08:00||;True|2026-01-01T23:29:35.2877898+08:00||;False|2026-01-01T23:27:39.5930556+08:00||;False|2026-01-01T23:24:52.0996222+08:00||;False|2026-01-01T23:24:09.0444840+08:00||;False|2026-01-01T23:24:06.1610789+08:00||;False|2026-01-01T23:24:03.3178410+08:00||;False|2026-01-01T23:22:56.2224992+08:00||;False|2026-01-01T23:22:47.8246988+08:00||;False|2026-01-01T23:22:43.2890820+08:00||;True|2026-01-01T23:21:03.6027351+08:00||;True|2026-01-01T23:07:57.5938094+08:00||;True|2025-12-29T18:55:45.8262096+08:00||;True|2025-12-28T00:21:04.1648410+08:00||;True|2025-12-28T00:18:49.2137559+08:00||;True|2025-12-28T00:14:18.1456892+08:00||;True|2025-12-28T00:11:06.6645248+08:00||;False|2025-12-28T00:10:49.4906020+08:00||;True|2025-12-27T23:51:57.6426264+08:00||;True|2025-12-27T23:40:08.4783210+08:00||;True|2025-12-27T14:59:32.0605406+08:00||;False|2025-12-27T14:59:21.2076690+08:00||;True|2025-12-27T12:58:06.9934830+08:00||;True|2025-12-27T12:51:45.3402320+08:00||;True|2025-12-27T12:45:49.9795040+08:00||;True|2025-12-27T12:42:13.9395619+08:00||;True|2025-12-27T11:32:35.8851241+08:00||;True|2025-12-27T11:32:11.1199261+08:00||;True|2025-12-27T11:31:34.3939619+08:00||;True|2025-12-26T22:39:54.4903900+08:00||;False|2025-12-26T22:39:38.9956198+08:00||;True|2025-12-26T13:29:16.3817938+08:00||;True|2025-12-26T13:13:27.1756564+08:00||;True|2025-12-26T13:12:27.5681845+08:00||;True|2025-12-25T21:53:39.9851108+08:00||;True|2025-12-25T21:14:06.5238213+08:00||;True|2025-12-25T14:05:40.5153425+08:00||;True|2025-12-25T00:52:42.0632072+08:00||;False|2025-12-25T00:52:36.5033522+08:00||;True|2025-12-24T20:47:03.4244585+08:00||;True|2025-12-24T20:38:49.1905853+08:00||;True|2025-12-24T20:38:18.7336590+08:00||;True|2025-12-24T20:33:27.1126773+08:00||;True|2025-12-24T20:32:29.2799273+08:00||;True|2025-12-23T20:55:43.6793723+08:00||;True|2025-12-23T20:54:55.9960612+08:00||;True|2025-12-21T13:23:11.0272294+08:00||;True|2025-12-21T13:22:56.8339811+08:00||;False|2025-12-21T13:22:50.2395530+08:00||;True|2025-12-21T13:11:36.6129339+08:00||;True|2025-12-21T12:15:18.4086793+08:00||;True|2025-12-21T12:15:11.4448190+08:00||;True|2025-12-20T14:05:36.6224332+08:00||;False|2025-12-20T14:05:28.6359828+08:00||;True|2025-12-20T13:58:30.1641630+08:00||;True|2025-12-20T13:55:16.1759645+08:00||;True|2025-12-20T12:16:22.5224516+08:00||;True|2025-12-19T09:50:16.9517676+08:00||;True|2025-12-19T09:49:47.0871734+08:00||;False|2025-12-19T09:49:36.7638757+08:00||;True|2025-12-19T09:35:13.2489248+08:00||;True|2025-12-14T19:09:59.9031104+08:00||;True|2025-12-13T21:21:10.0022707+08:00||;True|2025-12-11T22:07:16.6229994+08:00||;True|2025-12-11T22:05:56.7363206+08:00||;True|2025-12-11T22:01:07.5862406+08:00||;True|2025-12-11T22:00:43.5796594+08:00||;True|2025-12-08T21:20:37.8369271+08:00||;False|2025-12-08T21:20:21.1646252+08:00||;True|2025-12-08T20:51:50.6845619+08:00||;True|2025-12-08T16:43:45.2425324+08:00||;False|2025-12-08T16:42:23.0308163+08:00||;True|2025-12-08T16:41:52.4103868+08:00||;True|2025-12-08T16:41:49.8972006+08:00||;False|2025-12-08T16:41:39.5343442+08:00||;True|2025-12-08T12:40:19.2430740+08:00||;True|2025-12-08T12:02:30.6005542+08:00||;True|2025-12-08T11:34:29.6673185+08:00||;False|2025-12-08T11:30:56.2857042+08:00||;True|2025-12-08T10:52:43.7427594+08:00||;True|2025-12-08T07:05:03.2845531+08:00||;True|2025-12-07T23:02:10.0037815+08:00||;True|2025-12-07T22:48:25.7859648+08:00||;True|2025-12-07T20:49:13.6683281+08:00||;True|2025-12-07T08:47:30.1236366+08:00||;True|2025-12-06T13:14:32.4410202+08:00||;True|2025-12-06T13:07:29.7182102+08:00||;True|2025-12-06T13:05:46.2855366+08:00||;False|2025-12-06T13:05:40.3550904+08:00||;True|2025-12-06T13:03:47.8773880+08:00||;True|2025-12-06T13:03:28.9521030+08:00||;True|2025-12-05T23:11:51.5026151+08:00||;True|2025-12-05T12:46:26.1415079+08:00||;False|2025-12-05T12:46:19.1274332+08:00||;True|2025-12-05T09:04:36.7111717+08:00||;</History>
<LastFailureDetails /> <LastFailureDetails />
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+2 -2
View File
@@ -1,7 +1,7 @@
{ {
"deploy": "fn", //fn,docker "deploy": "docker", //fn,docker
"dbconn": "", "dbconn": "",
"tagName": "beta_1.9.6", //arm,beta "tagName": "beta_1.9.7", //arm,beta
"dbtype": "Sqlite", "dbtype": "Sqlite",
"fnVersion": "1.0.0" "fnVersion": "1.0.0"
} }
+16 -7
View File
@@ -446,10 +446,11 @@ namespace dy.net.job
foreach (var item in data.AwemeList) foreach (var item in data.AwemeList)
{ {
//if (!item.Desc.Contains("人生苦短")) //if (!item.Desc.Contains("人生苦短"))
////if (!item.Desc.Contains("如果你也喜欢")) //if (item.AwemeId!= "7202236830337551616")
//{ //{
// continue; // continue;
//} //}
//判断视频是否是强制删除且不再下载的视频 //判断视频是否是强制删除且不再下载的视频
var deleteVideo = await douyinCommonService.ExistDeleteVideo(item.AwemeId); var deleteVideo = await douyinCommonService.ExistDeleteVideo(item.AwemeId);
if (deleteVideo) if (deleteVideo)
@@ -754,7 +755,8 @@ namespace dy.net.job
await Task.Delay(_random.Next(1, 4) * 1000); await Task.Delay(_random.Next(1, 4) * 1000);
// 下载视频 // 下载视频
if (!await douyinHttpClientService.DownloadAsync(videoUrl, savePath, cookie.Cookies)) var (Success, ActualSavePath) = await douyinHttpClientService.DownloadAsync(videoUrl, savePath, cookie.Cookies);
if (!Success)
{ {
Log.Error($"{VideoType}-{item?.Author?.Nickname ?? ""}-视频[{DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId)}]下载失败!!!"); Log.Error($"{VideoType}-{item?.Author?.Nickname ?? ""}-视频[{DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId)}]下载失败!!!");
@@ -812,8 +814,8 @@ namespace dy.net.job
dynamicSavePaths.Add(dynamicSavePath); dynamicSavePaths.Add(dynamicSavePath);
continue; continue;
} }
var (Success, ActualSavePath) = await douyinHttpClientService.DownloadAsync(dynamicUrl, dynamicSavePath, cookie.Cookies);
if (!await douyinHttpClientService.DownloadAsync(dynamicUrl, dynamicSavePath, cookie.Cookies)) if (!Success)
{ {
Log.Error($"{VideoType}-{item?.Author?.Nickname ?? ""}-视频[{DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId)}]-00{i},下载失败!!!"); Log.Error($"{VideoType}-{item?.Author?.Nickname ?? ""}-视频[{DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId)}]-00{i},下载失败!!!");
} }
@@ -891,10 +893,18 @@ namespace dy.net.job
if (otherUrls.Count > 0) if (otherUrls.Count > 0)
{ {
Log.Debug($"{VideoType}-额外找到{otherUrls.Count}个视频地址,即将再次开始下载..."); Log.Debug($"{VideoType}-额外找到{otherUrls.Count}个视频地址,即将再次开始下载...");
var result2 = await douyinHttpClientService.DownloadAsync(videoUrl, savePath, cookie.Cookies, otherUrls); var (Success, ActualSavePath) = await douyinHttpClientService.DownloadAsync(videoUrl, savePath, cookie.Cookies, otherUrls);
if(Success)
{
Log.Debug($"{VideoType}-尝试多个地址后,下载成功,{savePath}"); Log.Debug($"{VideoType}-尝试多个地址后,下载成功,{savePath}");
} }
else else
{
Log.Error($"{VideoType}-尝试多个地址后,下载失败,{item.Desc}");
return (flowControl: false, value: null);
}
}
else
{ {
Log.Error($"{VideoType}-确实没有可以下载的视频链接2," + item.Desc); Log.Error($"{VideoType}-确实没有可以下载的视频链接2," + item.Desc);
return (flowControl: false, value: null); return (flowControl: false, value: null);
@@ -963,7 +973,6 @@ namespace dy.net.job
// 获取音乐URL // 获取音乐URL
var mp3Url = item.Music?.PlayUrl?.UrlList?.FirstOrDefault(); var mp3Url = item.Music?.PlayUrl?.UrlList?.FirstOrDefault();
var firstImage = item.Images.FirstOrDefault(); var firstImage = item.Images.FirstOrDefault();
int height = firstImage.Height; int height = firstImage.Height;
int width = firstImage.Width; int width = firstImage.Width;
@@ -1244,7 +1253,7 @@ namespace dy.net.job
// 如果封面文件不存在,则下载 // 如果封面文件不存在,则下载
if (!File.Exists(coverSavePath)) if (!File.Exists(coverSavePath))
{ {
var downRes = await douyinHttpClientService.DownloadAsync(coverUrl, coverSavePath, cookie.Cookies); await douyinHttpClientService.DownloadAsync(coverUrl, coverSavePath, cookie.Cookies);
} }
} }
+59 -8
View File
@@ -313,7 +313,7 @@ namespace dy.net.service
/// <param name="maxRetryCount">最大重试次数(默认3次)</param> /// <param name="maxRetryCount">最大重试次数(默认3次)</param>
/// <param name="initialRetryDelay">初始重试延迟(默认1秒,指数退避)</param> /// <param name="initialRetryDelay">初始重试延迟(默认1秒,指数退避)</param>
/// <returns>是否下载成功</returns> /// <returns>是否下载成功</returns>
public async Task<bool> DownloadAsync( public async Task<(bool Success, string ActualSavePath)> DownloadAsync(
string videoUrl, string videoUrl,
string savePath, string savePath,
string cookie, string cookie,
@@ -362,21 +362,21 @@ namespace dy.net.service
{ {
// 等待期间被取消,直接返回失败 // 等待期间被取消,直接返回失败
Serilog.Log.Information($"重试等待被取消:{videoUrl}"); Serilog.Log.Information($"重试等待被取消:{videoUrl}");
return false; return (false, savePath);
} }
} }
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{ {
// 主动取消,不重试 // 主动取消,不重试
Serilog.Log.Information($"下载被取消:{videoUrl}"); Serilog.Log.Information($"下载被取消:{videoUrl}");
return false; return (false, savePath);
} }
catch (Exception ex) catch (Exception ex)
{ {
// 不可重试的异常(如参数错误、权限不足等),直接失败 // 不可重试的异常(如参数错误、权限不足等),直接失败
Serilog.Log.Error(ex, $"下载失败(不可重试):{videoUrl}"); Serilog.Log.Error(ex, $"下载失败(不可重试):{videoUrl}");
CleanupIncompleteFile(savePath); // 清理不完整文件 CleanupIncompleteFile(savePath); // 清理不完整文件
return false; return (false, savePath);
} }
} }
} }
@@ -489,7 +489,7 @@ namespace dy.net.service
/// <summary> /// <summary>
/// 单次下载尝试(核心下载逻辑) /// 单次下载尝试(核心下载逻辑)
/// </summary> /// </summary>
private async Task<bool> TryDownloadOnceAsync( private async Task<(bool Success, string ActualSavePath)> TryDownloadOnceAsync(
string videoUrl, string videoUrl,
string savePath, string savePath,
string cookie, string cookie,
@@ -507,6 +507,11 @@ namespace dy.net.service
// 清理已存在的文件(避免占用) // 清理已存在的文件(避免占用)
CleanupIncompleteFile(savePath); CleanupIncompleteFile(savePath);
//传入的文件后缀名
string ext = Path.GetExtension(savePath);
string actualSavePath = savePath;
string detectedExtension = string.Empty;
using (var httpClient = _clientFactory.CreateClient("dy_download")) using (var httpClient = _clientFactory.CreateClient("dy_download"))
{ {
@@ -525,10 +530,52 @@ namespace dy.net.service
long? totalBytes = response.Content.Headers.ContentLength; long? totalBytes = response.Content.Headers.ContentLength;
// 读取流并写入文件 // 读取响应
using (var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false)) using (var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false))
{
//if (ext == ".mp3")
//{
// detectedExtension = DouyinFileUtils.GetFileExtensionByMagicNumber(responseStream);
//}
if (ext == ".mp3")
{
var contentType = response.Content.Headers.ContentType?.MediaType;
if (!string.IsNullOrEmpty(contentType))
{
if (contentType.Contains("audio/mp4") || contentType.Contains("audio/m4a"))
{
detectedExtension = "m4a";
}
else if (contentType.Contains("audio/mpeg") || contentType.Contains("audio/mp3"))
{
detectedExtension = "mp3";
}
else if (contentType.Contains("video/mp4"))
{
detectedExtension = "mp4";
}
}
}
if (!string.IsNullOrEmpty(detectedExtension))
{
string extension = Path.GetExtension(actualSavePath);
if (string.IsNullOrEmpty(extension))
{
actualSavePath += detectedExtension;
}
else
{
actualSavePath = Path.ChangeExtension(actualSavePath, detectedExtension.Trim('.'));
savePath = actualSavePath;
}
CleanupIncompleteFile(actualSavePath);
}
using (var fileStream = new FileStream( using (var fileStream = new FileStream(
savePath, actualSavePath, // 使用修正后的保存路径
FileMode.CreateNew, FileMode.CreateNew,
FileAccess.Write, FileAccess.Write,
FileShare.None, FileShare.None,
@@ -563,8 +610,10 @@ namespace dy.net.service
} }
} }
} }
}
return true; // 返回成功状态和实际的保存路径
return (Success: true, ActualSavePath: actualSavePath);
} }
@@ -711,4 +760,6 @@ namespace dy.net.service
} }
} }
+11 -3
View File
@@ -219,7 +219,8 @@ namespace dy.net.service
// 保存下载的音频(如果需要) // 保存下载的音频(如果需要)
if (downMp3) if (downMp3)
{ {
await SaveDownloadedFilesAsync(rawAudios, fileNamefolder, "mp3", Path.GetFileNameWithoutExtension(outputVideoPath)); var ext= Path.GetExtension(rawAudios[0]);
await SaveDownloadedFilesAsync(rawAudios, fileNamefolder, ext, Path.GetFileNameWithoutExtension(outputVideoPath));
} }
} }
@@ -407,8 +408,15 @@ namespace dy.net.service
try try
{ {
await douyinHttpClientService.DownloadAsync(url, savePath, cookie); var (Success, ActualSavePath) = await douyinHttpClientService.DownloadAsync(url, savePath, cookie);
successPaths.Add(savePath); if(Success)
{
successPaths.Add(ActualSavePath);
}
else
{
Serilog.Log.Error($"下载失败:{url} → {savePath}");
}
//Console.WriteLine($"下载成功:{url} → {savePath}"); //Console.WriteLine($"下载成功:{url} → {savePath}");
} }
catch (Exception ex) catch (Exception ex)
+59
View File
@@ -157,5 +157,64 @@
{ {
return HasDirectoryReadPermission(directoryPath) && HasDirectoryWritePermission(directoryPath); return HasDirectoryReadPermission(directoryPath) && HasDirectoryWritePermission(directoryPath);
} }
/// <summary>
/// 通过文件头魔数(前几个字节)识别真实文件类型
/// </summary>
public static string GetFileExtensionByMagicNumber(Stream stream)
{
// 读取前16个字节(足够识别常见格式)
byte[] magicBytes = new byte[16];
int readBytes = stream.Read(magicBytes, 0, magicBytes.Length);
//stream.Position = 0; // 读完重置指针
if (readBytes < 4) return ""; // 字节数不足,兜底
// 魔数匹配规则(核心:区分MP4视频和M4A音频)
// MP4/M4A 基础魔数:0x00 0x00 0x00 ?? 0x66 0x74 0x79 0x70 (ftyp)
if (magicBytes[4] == 0x66 && magicBytes[5] == 0x74 && magicBytes[6] == 0x79 && magicBytes[7] == 0x70)
{
// 读取ftyp后的字符,区分MP4/M4A
if (readBytes >= 12)
{
// MP4 特征:ftypmp42 / ftypisom / ftypmp41
string ftyp = System.Text.Encoding.ASCII.GetString(magicBytes, 8, 4);
if (ftyp == "mp42" || ftyp == "isom" || ftyp == "mp41")
{
// 进一步判断是否包含视频轨道(简化版:M4A只有音频,MP4可能含视频)
// 这里做简化区分:如果是纯音频则为m4a,否则为mp4
// (进阶版可解析MP4盒子,新手先按此规则)
return "m4a"; // 你原链接的真实类型
// 若要严格区分视频MP4,可扩展:return "mp4";
}
// M4A 特征:ftypM4A / ftypM4B / ftypM4P
else if (ftyp == "M4A " || ftyp == "M4B " || ftyp == "M4P ")
{
return "m4a";
}
}
// 兜底:MP4/M4A统一先按Content-Type辅助,无则按mp4
return "mp4";
}
// MP3 魔数:0xFF 0xFB 或 0x49 0x44 0x33 (ID3)
else if ((magicBytes[0] == 0xFF && magicBytes[1] == 0xFB) ||
(magicBytes[0] == 0x49 && magicBytes[1] == 0x44 && magicBytes[2] == 0x33))
{
return "mp3";
}
// 其他常见格式(可扩展)
else if (magicBytes[0] == 0xFF && magicBytes[1] == 0xD8) // JPG
{
return "jpg";
}
else if (magicBytes[0] == 0x89 && magicBytes[1] == 0x50 && magicBytes[2] == 0x4E && magicBytes[3] == 0x47) // PNG
{
return "png";
}
else
{
return ""; // 未知格式
}
}
} }
} }
+32 -27
View File
@@ -140,15 +140,17 @@ namespace dy.net.utils
Serilog.Log.Error($"获取音频时长失败,将使用图片总时长 ({audioDurationSeconds:F2}s) 作为视频时长: {ex.Message}"); Serilog.Log.Error($"获取音频时长失败,将使用图片总时长 ({audioDurationSeconds:F2}s) 作为视频时长: {ex.Message}");
} }
// 计算图片序列需要循环的次数 // 计算图片序列需要循环的次数
int loopCount = 1; int loopCount = 1;
double singleLoopDuration = imageList.Count * ImageDisplayDurationSeconds; int imageCount = imageList.Count; // 要循环的图片总数(对应loop的size参数)
double singleLoopDuration = imageCount * ImageDisplayDurationSeconds;
if (audioDurationSeconds > singleLoopDuration) if (audioDurationSeconds > singleLoopDuration)
{ {
loopCount = (int)Math.Ceiling(audioDurationSeconds / singleLoopDuration); loopCount = (int)Math.Ceiling(audioDurationSeconds / singleLoopDuration);
//Console.WriteLine($"图片序列将循环 {loopCount} 次以匹配音频时长"); //Console.WriteLine($"图片序列将循环 {loopCount} 次以匹配音频时长");
} }
// H264编码要求宽高必须为偶数 20260103 // H264编码要求宽高必须为偶数 20260103
if (VideoWidth % 2 != 0) if (VideoWidth % 2 != 0)
{ {
@@ -158,51 +160,54 @@ namespace dy.net.utils
{ {
VideoHeight++; VideoHeight++;
} }
var arguments = new List<string> var arguments = new List<string>
{ {
"-y", // 覆盖输出文件 "-y", // 覆盖输出文件
// 图片序列输入:恢复你原有的 -r,移除可能冲突的参数 // 图片序列输入:保留原有逻辑,修复帧率含义(-r 是输出帧率,输入用-framerate更准确)
"-f", "image2", "-f", "image2",
"-r", imageFps.ToString(CultureInfo.InvariantCulture), // 保留你原本的帧率参数 "-framerate", imageFps.ToString(CultureInfo.InvariantCulture), // 输入帧率(图片播放速度)
"-start_number", "0", // 仅增加:避免序列编号问题(不影响原有逻辑) "-start_number", "0", // 序列起始编号
"-i", imageSequencePattern, // 关键修复:去掉引号(原代码的引号是核心失败原因 "-i", imageSequencePattern, // 图片序列模板(无需引号,后续用ProcessStartInfo传参更安全
// 音频输入:同样去掉引号 // 音频输入
"-i", audioFilePath, "-i", audioFilePath,
// 滤镜修复:恢复简单写法,避免复杂参数(适配旧版 FFmpeg // 滤镜修复:补充size参数(核心!解决Number of frames to loop is not set报错
"-filter_complex", $"[0:v]loop={loopCount - 1}[v]", // 去掉额外参数,和你原逻辑一致 // loop=循环次数:size=要循环的帧数;loop=-1表示无限循环(配合-shortest更简洁)
"-filter_complex", $"[0:v]loop=loop={loopCount - 1}:size={imageCount}[v]",
// 流映射:去掉引号,恢复简单写法 // 流映射
"-map", "[v]", "-map", "[v]",
"-map", "1:a", "-map", "1:a",
// 视频编码:保留你的变量,只增加兼容性参数 // 视频编码:保留你的变量,确保兼容性
"-c:v", VideoCodec, // 保留你原本的编码变量(之前能跑通,说明该编码支持) "-c:v", VideoCodec,
"-preset", VideoPreset, // 保留原变量 "-preset", VideoPreset,
"-crf", $"{VideoCrf}", // 保留原变量 "-crf", $"{VideoCrf}",
"-s", $"{VideoWidth}x{VideoHeight}", "-s", $"{VideoWidth}x{VideoHeight}",
"-pix_fmt", "yuv420p", // 仅增加:兼容性关键(不影响原有逻辑) "-pix_fmt", "yuv420p", // 兼容所有播放器
"-profile:v", "main", // 仅增加:适配多数播放器(不冲突) "-profile:v", "main",
// 音频编码:保留你的变量,修复可能的无效值 // 音频编码:标准化参数,避免无效值
"-c:a", AudioCodec, // 保留原变量 "-c:a", AudioCodec,
"-b:a", $"{AudioBitrate}", // 保留原变量 "-b:a", $"{AudioBitrate}",
"-ac", "2", // 仅增加:避免单声道兼容问题 "-ac", "2", // 立体声
"-ar", "44100", // 仅增加:标准采样率 "-ar", "44100", // 标准采样率
// 封装优化:仅增加关键参数,不影响原有逻辑 // 封装优化
"-f", "mp4", // 明确格式(之前可能自动识别,现在显式声明更稳定) "-f", "mp4",
"-movflags", "+faststart", // 仅增加:解决部分播放器无法播放 "-movflags", "+faststart",
// 保留你原有的同步参数 // 同步参数:确保视频时长匹配音频
"-shortest", "-shortest",
// 输出路径:去掉引号(核心修复点) // 输出路径
outputVideoPath outputVideoPath
}; };
string args = string.Join(" ", arguments); string args = string.Join(" ", arguments);
//Console.WriteLine($"执行FFmpeg命令: {_ffmpegExecutablePath} {args}"); //Console.WriteLine($"执行FFmpeg命令: {_ffmpegExecutablePath} {args}");
@@ -285,7 +290,7 @@ namespace dy.net.utils
if (_ffmpegProcess.ExitCode != 0) if (_ffmpegProcess.ExitCode != 0)
{ {
throw new InvalidOperationException($"FFmpeg执行失败,退出码: {_ffmpegProcess.ExitCode}。请查看控制台输出获取详细错误信息。"); throw new InvalidOperationException($"FFmpeg执行失败,退出码: {_ffmpegProcess.ExitCode}。请查看控制台输出获取详细错误信息。执行命令:ffmpeg {arguments}");
} }
} }
finally finally