1、nfo文件优化,修复演员信息(视频作者)

2、图文视频,因版权原因无法下载的音频,系统配置新增默认音频上传入口,上传成功后,后面在遇到无法下载音频时,将用该音频进行图文视频合成的音频数据
3、增加动态视频合成配置。
4、容器重启后,手机端会连续跳转登录页很多次的bug修复
5、其他优化
This commit is contained in:
jianzhichu
2026-01-12 22:13:59 +08:00
parent 858a21ec9e
commit e32d783de4
21 changed files with 1286 additions and 483 deletions
+5 -1
View File
@@ -36,6 +36,7 @@ namespace dy.net.service
conf.PriorityLevel = "[{\"id\":1,\"name\":\"喜欢的视频\",\"sort\":1},{\"id\":2,\"name\":\"收藏的视频\",\"sort\":2},{\"id\":3,\"name\":\"关注的视频\",\"sort\":3}]";
}
conf.IsFirstRunning = true;//标记为程序刚启动第一次运行
conf.AutoDistinct = true;
sqlSugarClient.Updateable(conf).ExecuteCommand();
//兼容旧版本
return conf;
@@ -60,7 +61,10 @@ namespace dy.net.service
AutoDistinct = true,//默认开启
PriorityLevel = "[{\"id\":1,\"name\":\"喜欢的视频\",\"sort\":1},{\"id\":2,\"name\":\"收藏的视频\",\"sort\":2},{\"id\":3,\"name\":\"关注的视频\",\"sort\":3}]",
IsFirstRunning = true,
OnlySyncNew = true
OnlySyncNew = true,
DownDynamicVideo = false,
KeepDynamicVideo = false,
MegDynamicVideo = false
};
sqlSugarClient.Insertable(config).ExecuteCommand();
return config;
+25 -140
View File
@@ -11,12 +11,10 @@ namespace dy.net.service
/// </summary>
public class DouyinMergeVideoService
{
private readonly FFmpegHelper _fFmpegHelper;
private readonly DouyinHttpClientService douyinHttpClientService;
public DouyinMergeVideoService(FFmpegHelper fFmpegHelper,DouyinHttpClientService douyinHttpClientService)
public DouyinMergeVideoService(DouyinHttpClientService douyinHttpClientService)
{
_fFmpegHelper = fFmpegHelper;
this.douyinHttpClientService = douyinHttpClientService;
}
@@ -27,142 +25,23 @@ namespace dy.net.service
// 重试间隔(毫秒)
private const int RetryDelay = 1000;
/// <summary>
/// 视频合成
/// 视频合成一个视频
/// </summary>
/// <param name="cookie"></param>
/// <param name="rootPath"></param>
/// <param name="request"></param>
/// <param name="outputVideoPath"></param>
/// <param name="fileNamefolder"></param>
/// <param name="mergeImg2Viedo"></param>
/// <param name="downImage"></param>
/// <param name="downMp3"></param>
/// <param name="videoFilePaths"></param>
/// <param name="savePath"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
//public async Task<bool> MergeToVideo(string cookie,string rootPath, MediaMergeRequest request,string outputVideoPath,string fileNamefolder,bool mergeImg2Viedo,bool downImage=false,bool downMp3=false)
//{
// try
// {
// // 创建唯一临时目录(避免并发冲突)
// var tempDir = Path.Combine(rootPath, "temp", Guid.NewGuid().ToString());
// try
// {
// // 1. 下载图片
// var (rawImages, error) = await DownloadMediaAsync(request.ImageUrls, Path.Combine(tempDir, "raw-images"), "image_", "webp",cookie);
// if (!string.IsNullOrEmpty(error))
// {
// Serilog.Log.Error($"{error}");
// return false;
// }
// else
// {
// if(downImage)
// {
// for (int i = 0; i < rawImages.Length; i++)
// {
// string sourcePath = rawImages[i];
// // 重命名为有规律的文件名,如 temp_001.jpg, temp_002.png
// string extension = Path.GetExtension(sourcePath);
// string destFileName = $"temp_{i + 1:D3}{extension}"; // D3 确保是3位数字,不足补0
// string destPath = Path.Combine(fileNamefolder, destFileName);
// if (destPath.Contains("小可爱") || sourcePath.Contains("小可爱")) {
// Console.WriteLine("发现小可爱图片");
// }
// if (!File.Exists(destPath))
// File.Copy(sourcePath, destPath);
// }
// }
// }
// // 2. 下载音频
// var (rawAudios, audioError) = await DownloadMediaAsync(request.AudioUrls, Path.Combine(tempDir, "raw-audios"), "audio_", "mp3", cookie);
// if (!string.IsNullOrEmpty(audioError))
// {
// Serilog.Log.Error($"{audioError}");
// return false;
// }
// else
// {
// if(downMp3)
// {
// for (int i = 0; i < rawAudios.Length; i++)
// {
// string sourcePath = rawAudios[i];
// // 重命名为有规律的文件名,如 temp_001.mp3, temp_002.mp3
// string extension = Path.GetExtension(sourcePath);
// string destFileName = $"temp_{i + 1:D3}{extension}"; // D3 确保是3位数字,不足补0
// string destPath = Path.Combine(fileNamefolder, destFileName);
// if (!File.Exists(destPath))
// File.Copy(sourcePath, destPath);
// }
// }
// }
// if (!mergeImg2Viedo)
// {
// // 不合成视频,直接返回成功
// Serilog.Log.Debug($"不合成视频,直接返回");
// return true;
// }
// // 4. 合成视频
// //var outputVideoPath = Path.Combine(tempDir, "output", $"merged-video.{request.OutputFormat.ToLower()}");
// // 2. 创建帮助类实例
// // 在Docker容器内,FFmpeg通常在PATH中,所以直接用 "ffmpeg" 即可
// // 根据图片数量调整每张图片显示时长
// if (request.ImageUrls.Count <= 3)
// {
// request.ImageDurationPerSecond = 3;
// }
// if (request.ImageUrls.Count > 20)
// {
// request.ImageDurationPerSecond = 2;
// }
// // 3. (可选)自定义视频参数
// _fFmpegHelper.VideoWidth = 1080;
// _fFmpegHelper.VideoHeight = 1920;
// _fFmpegHelper.ImageDisplayDurationSeconds = request.ImageDurationPerSecond;
// _fFmpegHelper.OutputFrameRate = 30;
// // 4. 创建进度
// var progress = new Progress<double>(p =>
// {
// Console.WriteLine($"进度: {p:F2}%");
// });
// // 5. 执行合成任务
// using (var cancellationTokenSource = new CancellationTokenSource())
// {
// string resultPath = await _fFmpegHelper.CreateVideoFromImagesAndAudioAsync(
// rawImages,
// rawAudios[0],
// outputVideoPath,
// request.VideoWidth,
// request.VideoHeight,
// progress,
// cancellationTokenSource.Token);
// //Console.WriteLine($"视频合成成功!文件已保存至: {resultPath}");
// Serilog.Log.Debug($"视频合成成功!文件已保存至: {resultPath}");
// }
// }
// finally
// {
// // 清理临时目录(无论成功失败)
// if (Directory.Exists(tempDir))
// {
// Directory.Delete(tempDir, recursive: true);
// }
// }
// return true;
// }
// catch (Exception ex)
// {
// Serilog.Log.Error($"{ex.StackTrace}");
// return false;
// }
//}
public async Task<string> MergeMultipleVideosAsync(
List<string> videoFilePaths,
string savePath,
int width = 1080,
int height = 1920)
{
return await new FFmpegHelper().MergeMultipleVideosAsync(videoFilePaths, savePath, width, height);
}
/// <summary>
@@ -261,7 +140,16 @@ namespace dy.net.service
if (rawAudios.Length == 0)
{
rawAudios= new string[] { Path.Combine(AppContext.BaseDirectory,"mp3", "silent_10.mp3") };
var mp3Path = Path.Combine(AppContext.BaseDirectory, "mp3", "silent_10.mp3");
var uploadMp3 = Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "mp3"))
.Where(filePath => Path.GetFileNameWithoutExtension(filePath) != "silent_10")
.FirstOrDefault();
if (!string.IsNullOrWhiteSpace(uploadMp3) && File.Exists(uploadMp3))
{
mp3Path = uploadMp3;
}
rawAudios = new string[] { mp3Path };
Log.Debug("版权原因无法下载音频,使用默认无声音频文件");
}
@@ -298,7 +186,6 @@ namespace dy.net.service
}
}
/// <summary>
/// 保存下载的文件(图片/音频)到目标目录
/// </summary>
@@ -356,8 +243,6 @@ namespace dy.net.service
return false;
}
/// <summary>
/// 安全清理临时目录(避免文件被占用)
/// </summary>
+7 -1
View File
@@ -4,6 +4,7 @@ using dy.net.model;
using dy.net.repository;
using dy.net.utils;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
@@ -124,7 +125,7 @@ namespace dy.net.service
data.GraphicVideoSize = "<0.01";//避免显示0.00误导用户
}
}
data.Authors = list.GroupBy(x => x.Author).Select(x => new VideoStaticsItemDto { Name = x.Key, Count = x.LongCount(), Icon = x.FirstOrDefault().AuthorAvatarUrl }).OrderByDescending(d => d.Count).ToList();
data.Authors = list.GroupBy(x => x.Author).Select(x => new VideoStaticsItemDto { Name = x.Key, Count = x.LongCount(), Icon = x.LastOrDefault().AuthorAvatarUrl }).OrderByDescending(d => d.Count).ToList();
return data;
}
@@ -148,6 +149,11 @@ namespace dy.net.service
return await _dyCollectVideoRepository.GetPagedAsync(dto);
}
public async Task<List<DouyinVideo>> GetAllAsync()
{
return await _dyCollectVideoRepository.GetAllAsync();
}
/// <summary>
/// 关注的博主的视频如果配置为视频标题作为文件名,生成文件名
/// </summary>