Add - Added option to define the Metadata Title

Add - Added option to include the description in the Metadata
Add - Added option to include subtitles that only translate signs
Fix - en-Us Calendar language
This commit is contained in:
Elwador 2024-06-24 17:40:20 +02:00
parent 87c9c2d8ac
commit 29aac7ed8f
14 changed files with 152 additions and 107 deletions

View File

@ -167,6 +167,8 @@ public class CrAuth{
}
if (crunInstance.Token?.refresh_token != null){
HttpClientReq.Instance.SetETPCookie(crunInstance.Token.refresh_token);
await GetProfile();
}

View File

@ -198,6 +198,7 @@ public class CrEpisode(){
DownloadSpeed = 0
};
epMeta.AvailableSubs = item.SubtitleLocales;
epMeta.Description = item.Description;
if (episodeP.EpisodeAndLanguages.Langs.Count > 0){
epMeta.SelectedDubs = dubLang
.Where(language => episodeP.EpisodeAndLanguages.Langs.Any(epLang => epLang.CrLocale == language))

View File

@ -94,6 +94,7 @@ public class CrSeries(){
Time = 0,
DownloadSpeed = 0
};
epMeta.Description = item.Description;
epMeta.AvailableSubs = item.SubtitleLocales;
if (episode.Langs.Count > 0){
epMeta.SelectedDubs = dubLang

View File

@ -11,10 +11,12 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using Avalonia.Media;
using CRD.Utils;
using CRD.Utils.CustomList;
using CRD.Utils.DRM;
using CRD.Utils.Files;
using CRD.Utils.HLS;
using CRD.Utils.Muxing;
using CRD.Utils.Sonarr;
@ -148,7 +150,7 @@ public class Crunchyroll{
CrunOptions.SimultaneousDownloads = 2;
CrunOptions.AccentColor = Colors.SlateBlue.ToString();
CrunOptions.Theme = "System";
CrunOptions.SelectedCalendarLanguage = "de";
CrunOptions.SelectedCalendarLanguage = "default";
CrunOptions.DlVideoOnce = true;
CrunOptions.StreamEndpoint = "web/firefox";
CrunOptions.SubsAddScaledBorder = ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes;
@ -371,7 +373,7 @@ public class Crunchyroll{
}
public async Task<bool> DownloadEpisode(CrunchyEpMeta data, CrDownloadOptions options, bool? isSeries){
public async Task<bool> DownloadEpisode(CrunchyEpMeta data, CrDownloadOptions options){
ActiveDownloads++;
data.DownloadProgress = new DownloadProgress(){
@ -416,7 +418,7 @@ public class Crunchyroll{
SkipSubMux = options.SkipSubsMux,
Output = res.FileName,
Mp4 = options.Mp4,
VideoTitle = options.VideoTitle,
VideoTitle = res.VideoTitle,
Novids = options.Novids,
NoCleanup = options.Nocleanup,
DefaultAudio = Languages.FindLang(options.DefaultAudio),
@ -425,7 +427,8 @@ public class Crunchyroll{
ForceMuxer = options.Force,
SyncTiming = options.SyncTiming,
CcTag = options.CcTag,
KeepAllVideos = true
KeepAllVideos = true,
MuxDescription = options.IncludeVideoDescription
},
res.FileName);
@ -488,6 +491,15 @@ public class Crunchyroll{
filename = newFilePath;
}
bool muxDesc = false;
if (options.MuxDescription){
if (File.Exists($"{filename}.xml")){
muxDesc = true;
} else{
Console.Error.WriteLine("No xml description file found to mux description");
}
}
var merger = new Merger(new MergerOptions{
OnlyVid = data.Where(a => a.Type == DownloadMediaType.Video).Select(a => new MergerInput{ Language = a.Lang, Path = a.Path ?? string.Empty }).ToList(),
@ -508,7 +520,8 @@ public class Crunchyroll{
Sub = options.DefaultSub
},
CcTag = options.CcTag,
mp3 = muxToMp3
mp3 = muxToMp3,
MuxDescription = muxDesc
});
if (!File.Exists(CfgManager.PathFFMPEG)){
@ -1336,11 +1349,42 @@ public class Crunchyroll{
// variables.Add(new Variable("height", quality == 0 ? plQuality.Last().RESOLUTION.Height : plQuality[quality - 1].RESOLUTION.Height, false));
// variables.Add(new Variable("width", quality == 0 ? plQuality.Last().RESOLUTION.Width : plQuality[quality - 1].RESOLUTION.Width, false));
if (options.IncludeVideoDescription){
string fullPath = (Path.IsPathRooted(fileName) ? fileName : Path.Combine(fileDir, fileName)) + ".xml";
if (!File.Exists(fullPath)){
using (XmlWriter writer = XmlWriter.Create(fullPath)){
writer.WriteStartDocument();
writer.WriteStartElement("Tags");
writer.WriteStartElement("Tag");
writer.WriteStartElement("Targets");
writer.WriteElementString("TargetTypeValue", "50");
writer.WriteEndElement(); // End Targets
writer.WriteStartElement("Simple");
writer.WriteElementString("Name", "DESCRIPTION");
writer.WriteElementString("String", data.Description);
writer.WriteEndElement(); // End Simple
writer.WriteEndElement(); // End Tag
writer.WriteEndElement(); // End Tags
writer.WriteEndDocument();
}
}
Console.WriteLine($"{fileName} has been created with the description.");
}
return new DownloadResponse{
Data = files,
Error = dlFailed,
FileName = fileName.Length > 0 ? (Path.IsPathRooted(fileName) ? fileName : Path.Combine(fileDir, fileName)) : "./unknown",
ErrorText = ""
ErrorText = "",
VideoTitle = FileNameManager.ParseFileName(options.VideoTitle, variables, options.Numbers, options.Override).Last()
};
}
@ -1391,7 +1435,7 @@ public class Crunchyroll{
if (files.Any(a => a.Type == DownloadMediaType.Subtitle &&
(a.Language.CrLocale == langItem.CrLocale || a.Language.Locale == langItem.Locale) &&
a.Cc == isCc &&
a.Signs == isSigns)){
a.Signs == isSigns) || (!options.IncludeSignsSubs && isSigns)){
continue;
}
@ -1404,7 +1448,7 @@ public class Crunchyroll{
if (subsItem.format == "ass"){
subsAssReqResponse.ResponseContent = '\ufeff' + subsAssReqResponse.ResponseContent;
var sBodySplit = subsAssReqResponse.ResponseContent.Split(new[]{ "\r\n" }, StringSplitOptions.None).ToList();
// Insert 'ScaledBorderAndShadow: yes' after the second line
// Insert 'ScaledBorderAndShadow' after the second line
if (sBodySplit.Count > 2){
if (options.SubsAddScaledBorder == ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes){
sBodySplit.Insert(2, "ScaledBorderAndShadow: yes");
@ -1424,6 +1468,8 @@ public class Crunchyroll{
var keysList = FontsManager.ExtractFontsFromAss(subsAssReqResponse.ResponseContent);
sxData.Fonts = FontsManager.Instance.GetDictFromKeyList(keysList);
}
} else if (subsItem.format == "vtt"){
// TODO
}
File.WriteAllText(sxData.Path, subsAssReqResponse.ResponseContent);
@ -1591,6 +1637,11 @@ public class Crunchyroll{
}
temppbData.Meta = new PlaybackMeta(){ AudioLocale = playStream.AudioLocale, Versions = playStream.Versions, Bifs = new List<string>{ playStream.Bifs }, MediaId = mediaId };
if (playStream.Captions != null){
temppbData.Meta.Captions = playStream.Captions;
}
temppbData.Meta.Subtitles = new Subtitles();
foreach (var playStreamSubtitle in playStream.Subtitles){
Subtitle sub = playStreamSubtitle.Value;
@ -1646,6 +1697,11 @@ public class Crunchyroll{
}
temppbData.Meta = new PlaybackMeta(){ AudioLocale = playStream.AudioLocale, Versions = playStream.Versions, Bifs = new List<string>{ playStream.Bifs }, MediaId = mediaId };
if (playStream.Captions != null){
temppbData.Meta.Captions = playStream.Captions;
}
temppbData.Meta.Subtitles = new Subtitles();
foreach (var playStreamSubtitle in playStream.Subtitles){
Subtitle sub = playStreamSubtitle.Value;

View File

@ -6,7 +6,7 @@ using System.Linq;
using System.Text.RegularExpressions;
using CRD.Utils.Structs;
namespace CRD.Utils;
namespace CRD.Utils.Files;
public class FileNameManager{
public static List<string> ParseFileName(string input, List<Variable> variables, int numbers, List<string> @override){

View File

@ -55,7 +55,13 @@ public class HttpClientReq{
Path = "/",
};
var cookie2 = new Cookie("c_locale", "en-US"){
Domain = "crunchyroll.com",
Path = "/",
};
handler.CookieContainer.Add(cookie);
handler.CookieContainer.Add(cookie2);
}
public async Task<(bool IsOk, string ResponseContent)> SendHttpRequest(HttpRequestMessage request){

View File

@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using CRD.Utils.Structs;
using DynamicData;
namespace CRD.Utils.Muxing;
@ -36,7 +37,7 @@ public class Merger{
if (!hasVideo || options.KeepAllVideos == true){
args.Add($"-i \"{vid.Path}\"");
metaData.Add($"-map {index}:v");
metaData.Add($"-metadata:s:v:{index} title=\"{(options.VideoTitle ?? vid.Language.Name)}\"");
metaData.Add($"-metadata:s:v:{index} title=\"{(vid.Language.Name)}\"");
hasVideo = true;
index++;
}
@ -129,7 +130,7 @@ public class Merger{
args.Add("--video-tracks 0");
args.Add("--no-audio");
string trackName = $"{(options.VideoTitle ?? vid.Language.Name)}";
string trackName = $"{(vid.Language.Name)}";
args.Add($"--track-name 0:\"{trackName}\"");
args.Add($"--language 0:{vid.Language.Code}");
@ -194,6 +195,16 @@ public class Merger{
args.Add($"--chapters \"{options.Chapters[0].Path}\"");
}
if (!string.IsNullOrEmpty(options.VideoTitle)){
args.Add($"--title \"{options.VideoTitle}\"");
}
if (options.MuxDescription){
args.Add($"--global-tags \"{Path.Combine(Path.GetDirectoryName(options.Output), Path.GetFileNameWithoutExtension(options.Output))}.xml\"");
}
return string.Join(" ", args);
}
@ -231,6 +242,10 @@ public class Merger{
allMediaFiles.ForEach(file => DeleteFile(file.Path));
allMediaFiles.ForEach(file => DeleteFile(file.Path + ".resume"));
if (options.MuxDescription){
DeleteFile(Path.Combine(Path.GetDirectoryName(options.Output), Path.GetFileNameWithoutExtension(options.Output)) + ".xml");
}
// Delete chapter files if any
options.Chapters?.ForEach(chapter => DeleteFile(chapter.Path));
@ -278,6 +293,7 @@ public class CrunchyMuxOptions{
public bool? KeepAllVideos{ get; set; }
public bool? Novids{ get; set; }
public bool Mp4{ get; set; }
public bool MuxDescription{ get; set; }
public string ForceMuxer{ get; set; }
public bool? NoCleanup{ get; set; }
public string VideoTitle{ get; set; }
@ -302,8 +318,8 @@ public class MergerOptions{
public bool? SkipSubMux{ get; set; }
public MuxOptions Options{ get; set; }
public Defaults Defaults{ get; set; }
public bool mp3{ get; set; }
public bool MuxDescription{ get; set; }
}
public class MuxOptions{

View File

@ -56,14 +56,20 @@ public class CrDownloadOptions{
[YamlMember(Alias = "subs_add_scaled_border", ApplyNamingConventions = false)]
public ScaledBorderAndShadowSelection SubsAddScaledBorder{ get; set; }
[YamlMember(Alias = "include_signs_subs", ApplyNamingConventions = false)]
public bool IncludeSignsSubs{ get; set; }
[YamlMember(Alias = "mux_mp4", ApplyNamingConventions = false)]
public bool Mp4{ get; set; }
[YamlIgnore]
public List<string> Override{ get; set; }
[YamlIgnore]
public string VideoTitle{ get; set; }
[YamlMember(Alias = "mux_video_title", ApplyNamingConventions = false)]
public string? VideoTitle{ get; set; }
[YamlMember(Alias = "mux_video_description", ApplyNamingConventions = false)]
public bool IncludeVideoDescription{ get; set; }
[YamlIgnore]
public string Force{ get; set; }

View File

@ -236,6 +236,7 @@ public class CrunchyEpMeta{
public string? SeasonTitle{ get; set; }
public string? EpisodeNumber{ get; set; }
public string? EpisodeTitle{ get; set; }
public string? Description{ get; set; }
public string? SeasonId{ get; set; }
public string? Season{ get; set; }
public string? ShowId{ get; set; }

View File

@ -24,7 +24,7 @@ public class PlaybackMeta{
public List<PlaybackVersion>? Versions{ get; set; }
[JsonProperty("audio_locale")] public Locale? AudioLocale{ get; set; }
[JsonProperty("closed_captions")] public Subtitles? ClosedCaptions{ get; set; }
public Dictionary<string, object>? Captions{ get; set; }
public Dictionary<string, Caption>? Captions{ get; set; }
}
public class SubtitleInfo{

View File

@ -62,6 +62,8 @@ public struct Episode{
public struct DownloadResponse{
public List<DownloadedMedia> Data{ get; set; }
public string FileName{ get; set; }
public string VideoTitle{ get; set; }
public bool Error{ get; set; }
public string ErrorText{ get; set; }
}

View File

@ -227,7 +227,7 @@ public partial class DownloadItemModel : INotifyPropertyChanged{
epMeta.DownloadProgress.IsDownloading = true;
Paused = !epMeta.Paused && !isDownloading || epMeta.Paused;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Paused)));
await Crunchyroll.Instance.DownloadEpisode(epMeta, Crunchyroll.Instance.CrunOptions, false);
await Crunchyroll.Instance.DownloadEpisode(epMeta, Crunchyroll.Instance.CrunOptions);
}
}

View File

@ -38,6 +38,9 @@ public partial class SettingsPageViewModel : ViewModelBase{
[ObservableProperty]
private bool _addScaledBorderAndShadow = false;
[ObservableProperty]
private bool _includeSignSubs = false;
[ObservableProperty]
private ComboBoxItem _selectedScaledBorderAndShadow;
@ -49,6 +52,9 @@ public partial class SettingsPageViewModel : ViewModelBase{
[ObservableProperty]
private bool _muxToMp4;
[ObservableProperty]
private bool _includeEpisodeDescription;
[ObservableProperty]
private bool _downloadVideoForEveryDub;
@ -67,6 +73,9 @@ public partial class SettingsPageViewModel : ViewModelBase{
[ObservableProperty]
private string _fileName = "";
[ObservableProperty]
private string _fileTitle = "";
[ObservableProperty]
private ObservableCollection<MuxingParam> _mkvMergeOptions = new();
@ -319,6 +328,9 @@ public partial class SettingsPageViewModel : ViewModelBase{
AddScaledBorderAndShadow = options.SubsAddScaledBorder is ScaledBorderAndShadowSelection.ScaledBorderAndShadowNo or ScaledBorderAndShadowSelection.ScaledBorderAndShadowYes;
SelectedScaledBorderAndShadow = GetScaledBorderAndShadowFromOptions(options);
IncludeEpisodeDescription = options.IncludeVideoDescription;
FileTitle = options.VideoTitle ?? "";
IncludeSignSubs = options.IncludeSignsSubs;
DownloadVideo = !options.Novids;
DownloadAudio = !options.Noaudio;
DownloadVideoForEveryDub = !options.DlVideoOnce;
@ -375,6 +387,8 @@ public partial class SettingsPageViewModel : ViewModelBase{
UpdateSubAndDubString();
Crunchyroll.Instance.CrunOptions.IncludeVideoDescription = IncludeEpisodeDescription;
Crunchyroll.Instance.CrunOptions.VideoTitle = FileTitle;
Crunchyroll.Instance.CrunOptions.Novids = !DownloadVideo;
Crunchyroll.Instance.CrunOptions.Noaudio = !DownloadAudio;
Crunchyroll.Instance.CrunOptions.DlVideoOnce = !DownloadVideoForEveryDub;
@ -383,6 +397,7 @@ public partial class SettingsPageViewModel : ViewModelBase{
Crunchyroll.Instance.CrunOptions.SkipSubsMux = SkipSubMux;
Crunchyroll.Instance.CrunOptions.Numbers = LeadingNumbers;
Crunchyroll.Instance.CrunOptions.FileName = FileName;
Crunchyroll.Instance.CrunOptions.IncludeSignsSubs = IncludeSignSubs;
Crunchyroll.Instance.CrunOptions.SubsAddScaledBorder = GetScaledBorderAndShadowSelection();
@ -612,67 +627,13 @@ public partial class SettingsPageViewModel : ViewModelBase{
UpdateSettings();
}
partial void OnDownloadAudioChanged(bool value){
UpdateSettings();
protected override void OnPropertyChanged(PropertyChangedEventArgs e){
base.OnPropertyChanged(e);
if (e.PropertyName is nameof(SelectedSubs) or nameof(SelectedDubs) or nameof(CustomAccentColor) or nameof(ListBoxColor) or nameof(CurrentAppTheme) or nameof(UseCustomAccent) or nameof(LogMode)){
return;
}
partial void OnDownloadChaptersChanged(bool value){
UpdateSettings();
}
partial void OnDownloadVideoChanged(bool value){
UpdateSettings();
}
partial void OnFileNameChanged(string value){
UpdateSettings();
}
partial void OnLeadingNumbersChanged(int value){
UpdateSettings();
}
partial void OnMuxToMp4Changed(bool value){
UpdateSettings();
}
partial void OnSelectedHSLangChanged(ComboBoxItem value){
UpdateSettings();
}
partial void OnSimultaneousDownloadsChanged(int value){
UpdateSettings();
}
partial void OnSelectedAudioQualityChanged(ComboBoxItem? value){
UpdateSettings();
}
partial void OnSelectedVideoQualityChanged(ComboBoxItem? value){
UpdateSettings();
}
partial void OnHistoryChanged(bool value){
UpdateSettings();
}
partial void OnSonarrHostChanged(string value){
UpdateSettings();
}
partial void OnSonarrPortChanged(string value){
UpdateSettings();
}
partial void OnSonarrApiKeyChanged(string value){
UpdateSettings();
}
partial void OnSonarrUseSslChanged(bool value){
UpdateSettings();
}
partial void OnSonarrUseSonarrNumberingChanged(bool value){
UpdateSettings();
}
@ -685,33 +646,6 @@ public partial class SettingsPageViewModel : ViewModelBase{
}
}
partial void OnSelectedDefaultDubLangChanged(ComboBoxItem value){
UpdateSettings();
}
partial void OnSelectedDefaultSubLangChanged(ComboBoxItem value){
UpdateSettings();
}
partial void OnSkipSubMuxChanged(bool value){
UpdateSettings();
}
partial void OnDownloadVideoForEveryDubChanged(bool value){
UpdateSettings();
}
partial void OnSelectedStreamEndpointChanged(ComboBoxItem value){
UpdateSettings();
}
partial void OnAddScaledBorderAndShadowChanged(bool value){
UpdateSettings();
}
partial void OnSelectedScaledBorderAndShadowChanged(ComboBoxItem value){
UpdateSettings();
}
}
public class MuxingParam{

View File

@ -120,6 +120,12 @@
</controls:SettingsExpanderItem.Footer>
</controls:SettingsExpanderItem>
<controls:SettingsExpanderItem Content="Include Signs Subtitles ">
<controls:SettingsExpanderItem.Footer>
<CheckBox IsChecked="{Binding IncludeSignSubs}"> </CheckBox>
</controls:SettingsExpanderItem.Footer>
</controls:SettingsExpanderItem>
</controls:SettingsExpander>
<controls:SettingsExpander Header="History"
@ -284,6 +290,20 @@
</controls:SettingsExpanderItem.Footer>
</controls:SettingsExpanderItem>
<controls:SettingsExpanderItem Content="File title"
Description="${showTitle} ${seriesTitle} ${title} ${season} ${episode} ${height} ${width}">
<controls:SettingsExpanderItem.Footer>
<TextBox HorizontalAlignment="Left" MinWidth="250"
Text="{Binding FileTitle}" />
</controls:SettingsExpanderItem.Footer>
</controls:SettingsExpanderItem>
<controls:SettingsExpanderItem Content="Include Episode description">
<controls:SettingsExpanderItem.Footer>
<CheckBox IsChecked="{Binding IncludeEpisodeDescription}"> </CheckBox>
</controls:SettingsExpanderItem.Footer>
</controls:SettingsExpanderItem>
<controls:SettingsExpanderItem Content="Additional MKVMerge Options">
<controls:SettingsExpanderItem.Footer>