Skip to content

Commit cdfce8a

Browse files
authored
refactor: replace ytarchive with yt-dlp live-from-start (#12)
## 內容 - 移除 ytarchive 服務與 DI 註冊,改由 yt-dlp 支援 live-from-start 直播錄製 - 更新 IDownloaderService 介面與各 downloader 實作 - 調整 YouTube 錄製流程與 NameHelper 對應,清理設定字典 ## 變更檔案 - Interfaces/IDownloaderService.cs - SingletonServices/Downloader/YtdlpService.cs - SingletonServices/Downloader/FC2LiveDLService.cs - SingletonServices/Downloader/StreamlinkService.cs - SingletonServices/Downloader/TwitcastingRecorderService.cs - SingletonServices/Downloader/YtarchiveService.cs (removed) - SingletonServices/RecordService.cs - ScopedServices/PlatformService/YoutubeService.cs - Helper/NameHelper.cs - Program.cs - LivestreamRecorderService.sln.DotSettings ## 測試 - `dotnet build -c ApacheCouchDB_Release` (失敗: TOOLBOX_PATH 未設定) - `dotnet build -c AzureCosmosDB_Release` (失敗: TOOLBOX_PATH 未設定) Resolves #11 Signed-off-by: Jim Chen <Jim@ChenJ.im>
1 parent 92ada1d commit cdfce8a

11 files changed

Lines changed: 22 additions & 65 deletions

File tree

Helper/NameHelper.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public static string GetFileName(Video video, string platform)
2525
{
2626
return platform switch
2727
{
28-
"Youtube" or IYtarchiveService.Name or IYtdlpService.Name => $"{video.id}.mp4",
28+
"Youtube" or IYtdlpService.Name => $"{video.id}.mp4",
2929
"Twitch" or IStreamlinkService.Name => $"{video.id}.mp4",
3030
"Twitcasting" or ITwitcastingRecorderService.Name => $"{video.ChannelId}_{DateTime.UtcNow:yyyyMMddHHmmss}.mp4",
3131
"FC2" or IFc2LiveDLService.Name => $"{video.ChannelId}_{DateTime.UtcNow:yyyyMMddHHmmss}.mp4",
@@ -45,7 +45,7 @@ public static string PlatformType(string channelId, string platform)
4545
{
4646
return platform switch
4747
{
48-
"Youtube" or IYtarchiveService.Name or IYtdlpService.Name
48+
"Youtube" or IYtdlpService.Name
4949
=> channelId, // Youtube channelId already starts with "UC"
5050
"Twitch" or IStreamlinkService.Name
5151
=> channelId.StartsWith("TW") ? channelId[2..] : channelId,
@@ -61,7 +61,7 @@ public static string DatabaseType(string channelId, string platform)
6161
{
6262
return platform switch
6363
{
64-
"Youtube" or IYtarchiveService.Name or IYtdlpService.Name
64+
"Youtube" or IYtdlpService.Name
6565
=> channelId, // Youtube channelId always starts with "UC"
6666
"Twitch" or IStreamlinkService.Name
6767
=> channelId.StartsWith("TW") ? channelId : "TW" + channelId,
@@ -80,7 +80,7 @@ public static string PlatformType(string videoId, string platform)
8080
{
8181
return platform switch
8282
{
83-
"Youtube" or IYtarchiveService.Name or IYtdlpService.Name
83+
"Youtube" or IYtdlpService.Name
8484
=> videoId.StartsWith('Y') ? videoId[1..] : videoId,
8585
"Twitch" or IStreamlinkService.Name
8686
=> videoId.StartsWith("TW") ? videoId[2..] : videoId,
@@ -96,7 +96,7 @@ public static string DatabaseType(string videoId, string platform)
9696
{
9797
return platform switch
9898
{
99-
"Youtube" or IYtarchiveService.Name or IYtdlpService.Name
99+
"Youtube" or IYtdlpService.Name
100100
=> "Y" + videoId,
101101
"Twitch" or IStreamlinkService.Name
102102
=> "TW" + videoId,

Interfaces/IDownloaderService.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public interface IDownloaderService
77
Task CreateJobAsync(Video video,
88
bool useCookiesFile = false,
99
string? url = null,
10+
bool liveFromStart = false,
1011
CancellationToken cancellation = default);
1112
}
1213

@@ -25,11 +26,6 @@ public interface ITwitcastingRecorderService : IDownloaderService
2526
public const string Name = "twitcastingrecorder";
2627
}
2728

28-
public interface IYtarchiveService : IDownloaderService
29-
{
30-
public const string Name = "ytarchive";
31-
}
32-
3329
public interface IYtdlpService : IDownloaderService
3430
{
3531
public const string Name = "ytdlp";

LivestreamRecorderService.sln.DotSettings

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
<s:Boolean x:Key="/Default/UserDictionary/Words/=streamid/@EntryIndexedValue">True</s:Boolean>
55
<s:Boolean x:Key="/Default/UserDictionary/Words/=telop/@EntryIndexedValue">True</s:Boolean>
66
<s:Boolean x:Key="/Default/UserDictionary/Words/=twitcasting/@EntryIndexedValue">True</s:Boolean>
7-
<s:Boolean x:Key="/Default/UserDictionary/Words/=ytarchive/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
7+
</wpf:ResourceDictionary>

Program.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@
112112

113113
services.AddDiscordService(configuration);
114114

115-
services.AddSingleton<IYtarchiveService, YtarchiveService>();
116115
services.AddSingleton<IYtdlpService, YtdlpService>();
117116
services.AddSingleton<IStreamlinkService, StreamlinkService>();
118117
services.AddSingleton<ITwitcastingRecorderService, TwitcastingRecorderService>();

ScopedServices/PlatformService/YoutubeService.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class YoutubeService(
2626
RssService rSsService,
2727
IStorageService storageService,
2828
// ReSharper disable once SuggestBaseTypeForParameterInConstructor
29-
IYtarchiveService ytarchiveService,
29+
IYtdlpService ytdlpService,
3030
IHttpClientFactory httpClientFactory,
3131
IOptions<DiscordOption> discordOptions,
3232
IServiceProvider serviceProvider) : PlatformService(channelRepository,
@@ -434,9 +434,10 @@ public override async Task UpdateVideoDataAsync(Video video, CancellationToken c
434434

435435
if (video.Status == VideoStatus.WaitingToRecord)
436436
{
437-
await ytarchiveService.CreateJobAsync(video: video,
438-
useCookiesFile: channel?.UseCookiesFile == true,
439-
cancellation: cancellation);
437+
await ytdlpService.CreateJobAsync(video: video,
438+
useCookiesFile: channel?.UseCookiesFile == true,
439+
liveFromStart: true,
440+
cancellation: cancellation);
440441

441442
video.Status = VideoStatus.Recording;
442443
logger.LogInformation("{videoId} is now lived! Start recording.", video.id);

SingletonServices/Downloader/FC2LiveDLService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class Fc2LiveDLService(IJobService jobService) : IFc2LiveDLService
1111
public Task CreateJobAsync(Video video,
1212
bool useCookiesFile = false,
1313
string? url = null,
14+
bool liveFromStart = false,
1415
CancellationToken cancellation = default)
1516
{
1617
url ??= $"https://live.fc2.com/{NameHelper.ChangeId.ChannelId.PlatformType(video.ChannelId, Name)}";

SingletonServices/Downloader/StreamlinkService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class StreamlinkService(IJobService jobService) : IStreamlinkService
1111
public Task CreateJobAsync(Video video,
1212
bool useCookiesFile = false,
1313
string? url = null,
14+
bool liveFromStart = false,
1415
CancellationToken cancellation = default)
1516
{
1617
url ??= $"twitch.tv/{NameHelper.ChangeId.ChannelId.PlatformType(video.ChannelId, Name)}";

SingletonServices/Downloader/TwitcastingRecorderService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class TwitcastingRecorderService(IJobService jobService) : ITwitcastingRe
1111
public Task CreateJobAsync(Video video,
1212
bool useCookiesFile = false,
1313
string? url = null,
14+
bool liveFromStart = false,
1415
CancellationToken cancellation = default)
1516
{
1617
string channelId = url?.Split('/', StringSplitOptions.RemoveEmptyEntries).Last()

SingletonServices/Downloader/YtarchiveService.cs

Lines changed: 0 additions & 44 deletions
This file was deleted.

SingletonServices/Downloader/YtdlpService.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class YtdlpService(IJobService jobService) : IYtdlpService
1111
public Task CreateJobAsync(Video video,
1212
bool useCookiesFile = false,
1313
string? url = null,
14+
bool liveFromStart = false,
1415
CancellationToken cancellation = default)
1516
{
1617
string instanceName = NameHelper.GetInstanceName(Name, video.id);
@@ -37,6 +38,8 @@ public Task CreateJobAsync(Video video,
3738
url
3839
];
3940

41+
if (liveFromStart) args = ["--live-from-start", .. args];
42+
4043
// Workaround for twitcasting ERROR:
4144
// Initialization fragment found after media fragments, unable to download
4245
// https://github.com/yt-dlp/yt-dlp/issues/5497
@@ -68,9 +71,10 @@ public Task CreateJobAsync(Video video,
6871
command = ["dumb-init", "--", "sh", "-c"];
6972

7073
// cp under mountPath to make sure the permission is writable
74+
string liveFromStartArg = liveFromStart ? "--live-from-start " : string.Empty;
7175
args =
7276
[
73-
$"cp -r /cookies {mountPath}/cookies && yt-dlp --ignore-config --retries 30 --concurrent-fragments 16 --merge-output-format mp4 -S '+proto:http,+codec:h264' --embed-thumbnail --embed-metadata --no-part --cookies {mountPath}/cookies/{video.ChannelId}.txt -o '{fileName}' '{url}'"
77+
$"cp -r /cookies {mountPath}/cookies && yt-dlp {liveFromStartArg}--ignore-config --retries 30 --concurrent-fragments 16 --merge-output-format mp4 -S '+proto:http,+codec:h264' --embed-thumbnail --embed-metadata --no-part --cookies {mountPath}/cookies/{video.ChannelId}.txt -o '{fileName}' '{url}'"
7478
];
7579

7680
// Workaround for twitcasting ERROR:

0 commit comments

Comments
 (0)