feat: Add serial parameter to disable Ashdi multivoice for VODs and optimize direct HLS playback in AnimeON.

This commit is contained in:
Felix 2026-02-24 18:57:01 +02:00
parent 1c49df634a
commit b7aaf0cc93
6 changed files with 56 additions and 29 deletions

View File

@ -187,13 +187,13 @@ namespace AnimeON
return null;
}
public async Task<string> ParseAshdiPage(string url)
public async Task<string> ParseAshdiPage(string url, bool disableAshdiMultivoiceForVod = false)
{
var streams = await ParseAshdiPageStreams(url);
var streams = await ParseAshdiPageStreams(url, disableAshdiMultivoiceForVod);
return streams?.FirstOrDefault().link;
}
public async Task<List<(string title, string link)>> ParseAshdiPageStreams(string url)
public async Task<List<(string title, string link)>> ParseAshdiPageStreams(string url, bool disableAshdiMultivoiceForVod = false)
{
var streams = new List<(string title, string link)>();
try
@ -204,7 +204,7 @@ namespace AnimeON
new HeadersModel("Referer", "https://ashdi.vip/")
};
string requestUrl = AshdiRequestUrl(WithAshdiMultivoice(url));
string requestUrl = AshdiRequestUrl(WithAshdiMultivoice(url, enable: !disableAshdiMultivoiceForVod));
_onLog($"AnimeON: using proxy {_proxyManager.CurrentProxyIp} for {requestUrl}");
string html = await Http.Get(_init.cors(requestUrl), headers: headers, proxy: _proxyManager.Get());
if (string.IsNullOrEmpty(html))
@ -256,7 +256,7 @@ namespace AnimeON
return streams;
}
public async Task<string> ResolveEpisodeStream(int episodeId)
public async Task<string> ResolveEpisodeStream(int episodeId, bool disableAshdiMultivoiceForVod = false)
{
try
{
@ -279,7 +279,7 @@ namespace AnimeON
if (root.TryGetProperty("videoUrl", out var videoProp))
{
string videoUrl = videoProp.GetString();
return await ResolveVideoUrl(videoUrl);
return await ResolveVideoUrl(videoUrl, disableAshdiMultivoiceForVod);
}
}
catch (Exception ex)
@ -290,7 +290,7 @@ namespace AnimeON
return null;
}
public async Task<string> ResolveVideoUrl(string url)
public async Task<string> ResolveVideoUrl(string url, bool disableAshdiMultivoiceForVod = false)
{
if (string.IsNullOrEmpty(url))
return null;
@ -299,16 +299,19 @@ namespace AnimeON
return await ParseMoonAnimePage(url);
if (url.Contains("ashdi.vip/vod"))
return await ParseAshdiPage(url);
return await ParseAshdiPage(url, disableAshdiMultivoiceForVod);
return url;
}
private static string WithAshdiMultivoice(string url)
private static string WithAshdiMultivoice(string url, bool enable = true)
{
if (string.IsNullOrWhiteSpace(url))
return url;
if (!enable)
return url;
if (url.IndexOf("ashdi.vip/vod/", StringComparison.OrdinalIgnoreCase) < 0)
return url;

View File

@ -154,12 +154,32 @@ namespace AnimeON.Controllers
string seasonStr = selectedSeasonNumber.ToString();
string episodeStr = ep.Number.ToString();
string streamLink = !string.IsNullOrEmpty(ep.Hls) ? ep.Hls : ep.VideoUrl;
// Для серіалів пріоритет — готовий fileUrl з API episodes (без додаткового резолву).
if (!string.IsNullOrEmpty(ep.Hls))
{
List<HeadersModel> streamHeaders = null;
bool forceProxy = false;
if (ep.Hls.Contains("ashdi.vip", StringComparison.OrdinalIgnoreCase))
{
streamHeaders = new List<HeadersModel>()
{
new HeadersModel("User-Agent", "Mozilla/5.0"),
new HeadersModel("Referer", "https://ashdi.vip/")
};
forceProxy = true;
}
string readyStreamUrl = BuildStreamUrl(init, ep.Hls, streamHeaders, forceProxy);
episode_tpl.Append(episodeName, title ?? original_title, seasonStr, episodeStr, readyStreamUrl);
continue;
}
string streamLink = ep.VideoUrl;
bool needsResolve = selectedVoiceInfo.PlayerType == "moon" || selectedVoiceInfo.PlayerType == "ashdi";
if (string.IsNullOrEmpty(streamLink) && ep.EpisodeId > 0)
{
string callUrl = $"{host}/animeon/play?episode_id={ep.EpisodeId}";
string callUrl = $"{host}/animeon/play?episode_id={ep.EpisodeId}&serial=1";
episode_tpl.Append(episodeName, title ?? original_title, seasonStr, episodeStr, accsArgs(callUrl), "call");
continue;
}
@ -169,7 +189,7 @@ namespace AnimeON.Controllers
if (needsResolve || streamLink.Contains("moonanime.art") || streamLink.Contains("ashdi.vip/vod"))
{
string callUrl = $"{host}/animeon/play?url={HttpUtility.UrlEncode(streamLink)}";
string callUrl = $"{host}/animeon/play?url={HttpUtility.UrlEncode(streamLink)}&serial=1";
episode_tpl.Append(episodeName, title ?? original_title, seasonStr, episodeStr, accsArgs(callUrl), "call");
}
else
@ -354,7 +374,7 @@ namespace AnimeON.Controllers
}
[HttpGet("animeon/play")]
public async Task<ActionResult> Play(string url, int episode_id = 0, string title = null)
public async Task<ActionResult> Play(string url, int episode_id = 0, string title = null, int serial = 0)
{
await UpdateService.ConnectAsync(host);
@ -363,16 +383,17 @@ namespace AnimeON.Controllers
return Forbid();
var invoke = new AnimeONInvoke(init, hybridCache, OnLog, proxyManager);
OnLog($"AnimeON Play: url={url}, episode_id={episode_id}");
bool disableAshdiMultivoiceForVod = serial == 1;
OnLog($"AnimeON Play: url={url}, episode_id={episode_id}, serial={serial}");
string streamLink = null;
if (episode_id > 0)
{
streamLink = await invoke.ResolveEpisodeStream(episode_id);
streamLink = await invoke.ResolveEpisodeStream(episode_id, disableAshdiMultivoiceForVod);
}
else if (!string.IsNullOrEmpty(url))
{
streamLink = await invoke.ResolveVideoUrl(url);
streamLink = await invoke.ResolveVideoUrl(url, disableAshdiMultivoiceForVod);
}
else
{

View File

@ -25,7 +25,7 @@ namespace AnimeON
{
public class ModInit
{
public static double Version => 3.6;
public static double Version => 3.7;
public static OnlinesSettings AnimeON;
public static bool ApnHostProvided;

View File

@ -143,7 +143,7 @@ namespace Mikai.Controllers
if (NeedsResolve(voices[t].ProviderName, streamLink))
{
string callUrl = $"{host}/mikai/play?url={HttpUtility.UrlEncode(streamLink)}&title={HttpUtility.UrlEncode(displayTitle)}";
string callUrl = $"{host}/mikai/play?url={HttpUtility.UrlEncode(streamLink)}&title={HttpUtility.UrlEncode(displayTitle)}&serial=1";
episodeTpl.Append(episodeName, displayTitle, s.ToString(), ep.Number.ToString(), accsArgs(callUrl), "call");
}
else
@ -203,7 +203,7 @@ namespace Mikai.Controllers
}
[HttpGet("mikai/play")]
public async Task<ActionResult> Play(string url, string title = null)
public async Task<ActionResult> Play(string url, string title = null, int serial = 0)
{
await UpdateService.ConnectAsync(host);
@ -215,9 +215,9 @@ namespace Mikai.Controllers
return OnError("mikai", _proxyManager);
var invoke = new MikaiInvoke(init, hybridCache, OnLog, _proxyManager);
OnLog($"Mikai Play: url={url}");
OnLog($"Mikai Play: url={url}, serial={serial}");
string streamLink = await invoke.ResolveVideoUrl(url);
string streamLink = await invoke.ResolveVideoUrl(url, serial == 1);
if (string.IsNullOrEmpty(streamLink))
return OnError("mikai", _proxyManager);

View File

@ -111,7 +111,7 @@ namespace Mikai
}
}
public async Task<string> ResolveVideoUrl(string url)
public async Task<string> ResolveVideoUrl(string url, bool disableAshdiMultivoiceForVod = false)
{
if (string.IsNullOrWhiteSpace(url))
return null;
@ -120,7 +120,7 @@ namespace Mikai
return await ParseMoonAnimePage(url);
if (url.Contains("ashdi.vip", StringComparison.OrdinalIgnoreCase))
return await ParseAshdiPage(url);
return await ParseAshdiPage(url, disableAshdiMultivoiceForVod);
return url;
}
@ -171,13 +171,13 @@ namespace Mikai
return ApnHelper.WrapUrl(_init, url);
}
public async Task<string> ParseAshdiPage(string url)
public async Task<string> ParseAshdiPage(string url, bool disableAshdiMultivoiceForVod = false)
{
var streams = await ParseAshdiPageStreams(url);
var streams = await ParseAshdiPageStreams(url, disableAshdiMultivoiceForVod);
return streams?.FirstOrDefault().link;
}
public async Task<List<(string title, string link)>> ParseAshdiPageStreams(string url)
public async Task<List<(string title, string link)>> ParseAshdiPageStreams(string url, bool disableAshdiMultivoiceForVod = false)
{
var streams = new List<(string title, string link)>();
try
@ -188,7 +188,7 @@ namespace Mikai
new HeadersModel("Referer", "https://ashdi.vip/")
};
string requestUrl = AshdiRequestUrl(WithAshdiMultivoice(url));
string requestUrl = AshdiRequestUrl(WithAshdiMultivoice(url, enable: !disableAshdiMultivoiceForVod));
_onLog($"Mikai: using proxy {_proxyManager.CurrentProxyIp} for {requestUrl}");
string html = await Http.Get(_init.cors(requestUrl), headers: headers, proxy: _proxyManager.Get());
if (string.IsNullOrEmpty(html))
@ -250,11 +250,14 @@ namespace Mikai
};
}
private static string WithAshdiMultivoice(string url)
private static string WithAshdiMultivoice(string url, bool enable = true)
{
if (string.IsNullOrWhiteSpace(url))
return url;
if (!enable)
return url;
if (url.IndexOf("ashdi.vip/vod/", StringComparison.OrdinalIgnoreCase) < 0)
return url;

View File

@ -24,7 +24,7 @@ namespace Mikai
{
public class ModInit
{
public static double Version => 3.7;
public static double Version => 3.8;
public static OnlinesSettings Mikai;
public static bool ApnHostProvided;