diff --git a/README.md b/README.md
index ed4350a..c65e8e7 100644
--- a/README.md
+++ b/README.md
@@ -84,7 +84,7 @@ Cookie 及 `sec_user_id` 是同步功能的核心,需严格按步骤获取,
## 3. 默认账号密码(首次登录用)
首次访问后台管理页面时,使用以下默认账号密码:
- **用户名**:`douyin`
-- **密码**:`douyin2025`
+- **密码**:`douyin2026`
> ⚠️ **安全建议**:登录后修改密码。
@@ -96,8 +96,8 @@ Cookie 及 `sec_user_id` 是同步功能的核心,需严格按步骤获取,
| 镜像标签 | 架构 |
| ----------------- | -------------- |
-| `beta_1.9.4` | x86_64 (amd64) |
-| `arm_1.9.4` | ARM64 |
+| `beta_1.9.5` | x86_64 (amd64) |
+| `arm_1.9.5` | ARM64 |
### 构建命令示例
diff --git a/job/DouyinBasicSyncJob.cs b/job/DouyinBasicSyncJob.cs
index 47c493e..3e9a589 100644
--- a/job/DouyinBasicSyncJob.cs
+++ b/job/DouyinBasicSyncJob.cs
@@ -646,10 +646,17 @@ namespace dy.net.job
}
else
{
- //记录存在,但本地文件不存在,则继续下载。
- Log.Debug($"{VideoType}-视频-{exitVideo.AwemeId}记录存在,但本地文件缺失,删除记录,重新下载");
- //删除原来的记录
- await douyinVideoService.DeleteById(exitVideo.Id);
+ if (exitVideo.OnlyImgOrOnlyMp3)
+ {
+ return true;//说明是图文视频,不需要再下载视频了
+ }
+ else
+ {
+ //记录存在,但本地文件不存在,则继续下载。
+ Log.Debug($"{VideoType}-视频-{exitVideo.AwemeId}记录存在,但本地文件缺失,删除记录,重新下载");
+ //删除原来的记录
+ await douyinVideoService.DeleteById(exitVideo.Id);
+ }
}
}
}
@@ -768,7 +775,7 @@ namespace dy.net.job
// 生成NFO文件
await GenerateNfoFile(saveFolder, item, avatarUrl, cookie, config);
// 创建视频实体
- return CreateVideoEntity(cookie, item, v, savePath, saveFolder, tag1, tag2, tag3, avatarSavePath, avatarUrl, data);
+ return CreateVideoEntity(config,cookie, item, v, savePath, saveFolder, tag1, tag2, tag3, avatarSavePath, avatarUrl, data);
}
@@ -837,7 +844,7 @@ namespace dy.net.job
DataSize = DouyinFileUtils.GetTotalFileSize(dynamicSavePaths) // 合成视频的文件大小
}
};
- return CreateVideoEntity(cookie, item, virtualBitRate, dynamicSavePaths.FirstOrDefault(), saveFolder, tag1, tag2, tag3,"", "", data,dynamicSavePaths);
+ return CreateVideoEntity(config,cookie, item, virtualBitRate, dynamicSavePaths.FirstOrDefault(), saveFolder, tag1, tag2, tag3,"", "", data,dynamicSavePaths);
}
@@ -978,7 +985,7 @@ namespace dy.net.job
// 获取不带扩展名的完整路径
- string fullPathWithoutExtension = Path.Combine(Path.GetDirectoryName(savePath),Path.GetFileNameWithoutExtension(savePath) );
+ //string fullPathWithoutExtension = Path.Combine(Path.GetDirectoryName(savePath),Path.GetFileNameWithoutExtension(savePath) );
if (config.DownImageVideo)
{
// 检查合成后的视频文件是否有效
@@ -1021,7 +1028,7 @@ namespace dy.net.job
};
// 创建视频实体
- var videoEntity = CreateVideoEntity(
+ var videoEntity = CreateVideoEntity(config,
cookie, item, virtualBitRate, savePath, fileNamefolder,
tag1, tag2, tag3, avatarSavePath, avatarUrl, data);
@@ -1240,6 +1247,7 @@ namespace dy.net.job
/// 创建视频实体
/// 根据视频信息、下载路径等创建DouyinVideo实体对象
///
+ /// 配置
/// 用户Cookie
/// 视频信息
/// 视频码率信息
@@ -1253,13 +1261,13 @@ namespace dy.net.job
/// 视频信息对象
/// 动态视频
/// 创建的视频实体对象
- private DouyinVideo CreateVideoEntity(
+ private DouyinVideo CreateVideoEntity(AppConfig config,
DouyinCookie cookie, Aweme item, VideoBitRate bitRate, string savePath, string saveFolder,
string tag1, string tag2, string tag3, string avatarSavePath, string avatarUrl, DouyinVideoInfo data,List dynamicVideos=null)
{
var diffs = GetVideoEntityDifferences(cookie, item);
- var video= new DouyinVideo
+ var video = new DouyinVideo
{
ViedoType = VideoType,
AwemeId = item.AwemeId,
@@ -1283,7 +1291,8 @@ namespace dy.net.job
VideoCoverSavePath = Path.Combine(saveFolder, "poster.jpg"),
SyncTime = DateTime.Now,
DyUserId = item.AuthorUserId == 0 ? item.Author?.Uid : item.AuthorUserId.ToString(),
- CookieId = cookie.Id
+ CookieId = cookie.Id,
+ OnlyImgOrOnlyMp3 = string.IsNullOrWhiteSpace(savePath) && !config.DownImageVideo && (config.DownImage || config.DownMp3)
};
if (dynamicVideos != null && dynamicVideos.Count > 0)
{
diff --git a/model/DouyinVideo.cs b/model/DouyinVideo.cs
index 0365a0e..d65c4cc 100644
--- a/model/DouyinVideo.cs
+++ b/model/DouyinVideo.cs
@@ -154,5 +154,10 @@ namespace dy.net.model
// 普通字符串字段,显式标记为 SQLite TEXT 类型
[SugarColumn(ColumnDataType = "TEXT", Length = -1,IsNullable =true)]
public string DynamicVideos { get; set; }
+
+ ///
+ /// 是否仅下载图片或仅下载音频
+ ///
+ public bool OnlyImgOrOnlyMp3 { get; set; }
}
}
diff --git a/service/AdminUserService.cs b/service/AdminUserService.cs
index ef93824..75e5054 100644
--- a/service/AdminUserService.cs
+++ b/service/AdminUserService.cs
@@ -35,7 +35,7 @@ namespace dy.net.service
AdminUserInfo userInfo = new AdminUserInfo
{
UserName = "douyin",
- Password = "douyin2025",
+ Password = "douyin2026",
CreateTime = DateTime.Now
};
return _userRepository.InitUser(userInfo);
diff --git a/service/DouyinCookieService.cs b/service/DouyinCookieService.cs
index a55fbe9..33eb951 100644
--- a/service/DouyinCookieService.cs
+++ b/service/DouyinCookieService.cs
@@ -52,7 +52,7 @@ namespace dy.net.service
}
var cookie = new DouyinCookie
{
- UserName = "douyin2025",
+ UserName = "douyin2026",
Cookies = "-",
SecUserId = "-",
Id = IdGener.GetLong().ToString(),
diff --git a/service/DouyinMergeVideoService.cs b/service/DouyinMergeVideoService.cs
index d3cb1ac..5450cc0 100644
--- a/service/DouyinMergeVideoService.cs
+++ b/service/DouyinMergeVideoService.cs
@@ -301,7 +301,7 @@ namespace dy.net.service
///
/// 保存下载的文件(图片/音频)到目标目录
///
- private async Task SaveDownloadedFilesAsync(string[] sourcePaths, string targetFolder, string defaultExt,string videoFileName)
+ private static async Task SaveDownloadedFilesAsync(string[] sourcePaths, string targetFolder, string defaultExt,string videoFileName)
{
if (sourcePaths == null || sourcePaths.Length == 0) return;
Directory.CreateDirectory(targetFolder); // 确保目标目录存在
diff --git a/service/DouyinVideoService.cs b/service/DouyinVideoService.cs
index 0e3ff62..89e06e4 100644
--- a/service/DouyinVideoService.cs
+++ b/service/DouyinVideoService.cs
@@ -199,7 +199,7 @@ namespace dy.net.service
// 3. 构建重新下载记录(提前准备数据,避免事务内耗时操作)
var reDownList = new List();
- var filePathsToDelete = new List(); // 收集待删除文件路径,统一处理
+ var filePathsToDelete = new List<(string path,bool onlyImgOrMp3)>(); // 收集待删除文件路径,统一处理
foreach (var video in videos)
{
@@ -221,7 +221,7 @@ namespace dy.net.service
CookieId = video.CookieId
});
- filePathsToDelete.Add(video.VideoSavePath);
+ filePathsToDelete.Add((video.VideoSavePath,video.OnlyImgOrOnlyMp3));
}
// 无有效重新下载记录时直接返回
@@ -248,23 +248,35 @@ namespace dy.net.service
// 5. 文件删除(非事务操作,失败不回滚数据库,可根据业务调整)
// 采用异步文件操作,避免同步IO阻塞线程(需.NET 5+支持)
- foreach (var path in filePathsToDelete)
+ foreach (var video in filePathsToDelete)
{
try
{
- if (File.Exists(path))
+ if (File.Exists(video.path))
{
- File.Delete(path); // 异步删除,提升并发性能
- Serilog.Log.Debug("视频文件删除成功:Path={0}", path);
+ File.Delete(video.path); // 异步删除,提升并发性能
+ Serilog.Log.Debug("视频文件删除成功:Path={0}", video);
+
+ if (!video.onlyImgOrMp3)//如果是纯图片或纯音频文件,则不删除所在文件夹
+ {
+ //检查这个路径所在文件夹是否还有其他视频文件,如果没有则删除这个文件夹
+ var dir = Path.GetDirectoryName(video.Item1);
+
+ bool hasMp4File = Directory.EnumerateFiles(dir, "*.mp4", SearchOption.TopDirectoryOnly).Any(); // 只要存在一个MP4文件就返回true;
+ if (!hasMp4File)
+ {
+ Directory.Delete(dir, true);
+ }
+ }
}
else
{
- Serilog.Log.Error("视频文件不存在,跳过删除:Path={0}", path);
+ Serilog.Log.Error("视频文件不存在,跳过删除:Path={0}", video);
}
}
catch (IOException ex)
{
- Serilog.Log.Error(ex, "视频文件删除失败:Path={0}", path);
+ Serilog.Log.Error(ex, "视频文件删除失败:Path={0}", video);
}
}