using System.Threading.Channels; namespace ACBuildService; public static class VideoDownload { private static readonly Channel _queue = Channel.CreateUnbounded(); private static readonly CancellationTokenSource _cts = new CancellationTokenSource(); private static readonly TimeSpan _interval = TimeSpan.FromSeconds(20); static VideoDownload() { Task.Run(ProcessQueueAsync); } public static void Add(string shareText) { _queue.Writer.TryWrite(shareText); } private static async Task ProcessQueueAsync() { var timer = new PeriodicTimer(_interval); try { while (await _queue.Reader.WaitToReadAsync(_cts.Token) && await timer.WaitForNextTickAsync(_cts.Token)) { if (_queue.Reader.TryRead(out var shareText)) { // 这里开始处理任务,这个处理过程本身的时间不计入间隔 // PeriodicTimer 会保证两次 WaitForNextTickAsync 之间间隔10秒 await ProcessVideoDownloadAsync(shareText); } } } catch (OperationCanceledException) { // 正常取消 } } private static async Task ProcessVideoDownloadAsync(string shareText) { try { var service = GetService(shareText); if (service != null) { Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 开始处理: {shareText}"); await DownloadVideoAsync(service, shareText); Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 处理完成: {shareText}"); } } catch (Exception ex) { Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 处理失败: {shareText}, 错误: {ex.Message}"); } } // 模拟下载视频的方法 private static async Task DownloadVideoAsync(DownloadPlatforms service, string shareText) { //开始解析数据 var videoModel = await service.ParseShare(shareText); if (videoModel == null) return; var rootPath = $"{HttpService.BaseRootPath}videos/"; var t = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); var fileName = $"{t}.mp4"; var filePath = Path.Combine(rootPath, fileName); if (File.Exists(filePath)) { Log.Error("文件已存在"); return; } var ret = await service.DownloadAsync(videoModel.VideoUrl, rootPath, fileName, null, null); if (ret) { var dbItem = new VideoTable { SourcePath = shareText, FilePath = fileName, AuthorName = videoModel.AuthorName, Title = videoModel.Title, Desc = videoModel.Desc, Duration = videoModel.Duration, Like = (int)videoModel.DiggCount, Collect = (int)videoModel.CollectCount, Message = (int)videoModel.CommentCount, Share = (int)videoModel.ShareCount, CreateTime = DateTime.Now }; DB.Main.Insertable(dbItem).ExecuteCommand(); } //解析数据后等待一会 await Task.Delay(3000); } #region Service private static Dictionary _services = new Dictionary(); private static DownloadPlatforms GetService(string text) { var platform = GetPlatform(text); if (_services.TryGetValue(platform, out var value)) { return value; } if (platform == ShortVideoPlatformEnum.DouYin) { value = new DouYin(); } else if (platform == ShortVideoPlatformEnum.KuaiShou) { value = new KuaiShou(); } if (value != null) { _services[platform] = value; } return value; } private static ShortVideoPlatformEnum GetPlatform(string text) { if (text.Contains("douyin")) { return ShortVideoPlatformEnum.DouYin; } if (text.Contains("kuaishou")) { return ShortVideoPlatformEnum.KuaiShou; } return ShortVideoPlatformEnum.None; } #endregion }