支持通过时长筛选 `plistDurMin`
This commit is contained in:
parent
724a5c9fa2
commit
43cb264374
|
@ -386,31 +386,40 @@ namespace N_m3u8DL_RE.Common.Resource
|
||||||
(
|
(
|
||||||
zhCN: "通过正则表达式选择符合要求的视频流. 你能够以:分隔形式指定如下参数:\r\n\r\n" +
|
zhCN: "通过正则表达式选择符合要求的视频流. 你能够以:分隔形式指定如下参数:\r\n\r\n" +
|
||||||
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX:frame=REGEX\r\n" +
|
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX:frame=REGEX\r\n" +
|
||||||
"segsMin=number:segsMax=number:ch=REGEX:range=REGEX:url=REGEX:for=FOR\r\n\r\n" +
|
"segsMin=number:segsMax=number:ch=REGEX:range=REGEX:url=REGEX\r\n" +
|
||||||
|
"plistDurMin=hms:plistDurMax=hms:for=FOR\r\n\r\n" +
|
||||||
"* for=FOR: 选择方式. best[number], worst[number], all (默认: best)\r\n\r\n" +
|
"* for=FOR: 选择方式. best[number], worst[number], all (默认: best)\r\n\r\n" +
|
||||||
"例如: \r\n" +
|
"例如: \r\n" +
|
||||||
"# 选择最佳视频\r\n" +
|
"# 选择最佳视频\r\n" +
|
||||||
"-sv best\r\n" +
|
"-sv best\r\n" +
|
||||||
"# 选择4K+HEVC视频\r\n" +
|
"# 选择4K+HEVC视频\r\n" +
|
||||||
"-sv res=\"3840*\":codec=hvc1:for=best\r\n",
|
"-sv res=\"3840*\":codec=hvc1:for=best\r\n" +
|
||||||
|
"# 选择长度大于1小时20分钟30秒的视频\r\n" +
|
||||||
|
"-sv plistDurMin=\"1h20m30s\":for=best\r\n",
|
||||||
zhTW: "通過正則表達式選擇符合要求的影片軌. 你能夠以:分隔形式指定如下參數:\r\n\r\n" +
|
zhTW: "通過正則表達式選擇符合要求的影片軌. 你能夠以:分隔形式指定如下參數:\r\n\r\n" +
|
||||||
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX:frame=REGEX\r\n" +
|
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX:frame=REGEX\r\n" +
|
||||||
"segsMin=number:segsMax=number:ch=REGEX:range=REGEX:url=REGEX:for=FOR\r\n\r\n" +
|
"segsMin=number:segsMax=number:ch=REGEX:range=REGEX:url=REGEX\r\n" +
|
||||||
|
"plistDurMin=hms:plistDurMax=hms:for=FOR\r\n\r\n" +
|
||||||
"* for=FOR: 選擇方式. best[number], worst[number], all (默認: best)\r\n\r\n" +
|
"* for=FOR: 選擇方式. best[number], worst[number], all (默認: best)\r\n\r\n" +
|
||||||
"例如: \r\n" +
|
"例如: \r\n" +
|
||||||
"# 選擇最佳影片\r\n" +
|
"# 選擇最佳影片\r\n" +
|
||||||
"-sv best\r\n" +
|
"-sv best\r\n" +
|
||||||
"# 選擇4K+HEVC影片\r\n" +
|
"# 選擇4K+HEVC影片\r\n" +
|
||||||
"-sv res=\"3840*\":codec=hvc1:for=best\r\n",
|
"-sv res=\"3840*\":codec=hvc1:for=best\r\n" +
|
||||||
|
"# 選擇長度大於1小時20分鐘30秒的影片\r\n" +
|
||||||
|
"-sv plistDurMin=\"1h20m30s\":for=best\r\n",
|
||||||
enUS: "Select video streams by regular expressions. OPTIONS is a colon separated list of:\r\n\r\n" +
|
enUS: "Select video streams by regular expressions. OPTIONS is a colon separated list of:\r\n\r\n" +
|
||||||
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX:frame=REGEX\r\n" +
|
"id=REGEX:lang=REGEX:name=REGEX:codec=REGEX:res=REGEX:frame=REGEX\r\n" +
|
||||||
"segsMin=number:segsMax=number:ch=REGEX:range=REGEX:url=REGEX:for=FOR\r\n\r\n" +
|
"segsMin=number:segsMax=number:ch=REGEX:range=REGEX:url=REGEX\r\n" +
|
||||||
|
"plistDurMin=hms:plistDurMax=hms:for=FOR\r\n\r\n" +
|
||||||
"* for=FOR: Select type. best[number], worst[number], all (Default: best)\r\n\r\n" +
|
"* for=FOR: Select type. best[number], worst[number], all (Default: best)\r\n\r\n" +
|
||||||
"Examples: \r\n" +
|
"Examples: \r\n" +
|
||||||
"# select best video\r\n" +
|
"# select best video\r\n" +
|
||||||
"-sv best\r\n" +
|
"-sv best\r\n" +
|
||||||
"# select 4K+HEVC video\r\n" +
|
"# select 4K+HEVC video\r\n" +
|
||||||
"-sv res=\"3840*\":codec=hvc1:for=best\r\n"
|
"-sv res=\"3840*\":codec=hvc1:for=best\r\n" +
|
||||||
|
"# Select best video with duration longer than 1 hour 20 minutes 30 seconds\r\n" +
|
||||||
|
"-sv plistDurMin=\"1h20m30s\":for=best\r\n"
|
||||||
),
|
),
|
||||||
["cmd_selectAudio"] = new TextContainer
|
["cmd_selectAudio"] = new TextContainer
|
||||||
(
|
(
|
||||||
|
|
|
@ -274,6 +274,14 @@ namespace N_m3u8DL_RE.CommandLine
|
||||||
if (!string.IsNullOrEmpty(segsMax))
|
if (!string.IsNullOrEmpty(segsMax))
|
||||||
streamFilter.SegmentsMaxCount = long.Parse(segsMax);
|
streamFilter.SegmentsMaxCount = long.Parse(segsMax);
|
||||||
|
|
||||||
|
var plistDurMin = p.GetValue("plistDurMin");
|
||||||
|
if (!string.IsNullOrEmpty(plistDurMin))
|
||||||
|
streamFilter.PlaylistMinDur = OtherUtil.ParseSeconds(plistDurMin);
|
||||||
|
|
||||||
|
var plistDurMax = p.GetValue("plistDurMax");
|
||||||
|
if (!string.IsNullOrEmpty(plistDurMax))
|
||||||
|
streamFilter.PlaylistMaxDur = OtherUtil.ParseSeconds(plistDurMax);
|
||||||
|
|
||||||
return streamFilter;
|
return streamFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ namespace N_m3u8DL_RE.Entity
|
||||||
public Regex? UrlReg { get; set; }
|
public Regex? UrlReg { get; set; }
|
||||||
public long? SegmentsMinCount { get; set; }
|
public long? SegmentsMinCount { get; set; }
|
||||||
public long? SegmentsMaxCount { get; set; }
|
public long? SegmentsMaxCount { get; set; }
|
||||||
|
public double? PlaylistMinDur { get; set; }
|
||||||
|
public double? PlaylistMaxDur { get; set; }
|
||||||
|
|
||||||
public string For { get; set; } = "best";
|
public string For { get; set; } = "best";
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ namespace N_m3u8DL_RE.Util
|
||||||
inputs = inputs.Where(i => i.SegmentsCount < filter.SegmentsMaxCount);
|
inputs = inputs.Where(i => i.SegmentsCount < filter.SegmentsMaxCount);
|
||||||
if (filter.SegmentsMinCount != null && inputs.All(i => i.SegmentsCount > 0))
|
if (filter.SegmentsMinCount != null && inputs.All(i => i.SegmentsCount > 0))
|
||||||
inputs = inputs.Where(i => i.SegmentsCount > filter.SegmentsMinCount);
|
inputs = inputs.Where(i => i.SegmentsCount > filter.SegmentsMinCount);
|
||||||
|
if (filter.PlaylistMinDur != null)
|
||||||
|
inputs = inputs.Where(i => i.Playlist?.TotalDuration > filter.PlaylistMinDur);
|
||||||
|
if (filter.PlaylistMaxDur != null)
|
||||||
|
inputs = inputs.Where(i => i.Playlist?.TotalDuration < filter.PlaylistMaxDur);
|
||||||
|
|
||||||
var bestNumberStr = filter.For.Replace("best", "");
|
var bestNumberStr = filter.For.Replace("best", "");
|
||||||
var worstNumberStr = filter.For.Replace("worst", "");
|
var worstNumberStr = filter.For.Replace("worst", "");
|
||||||
|
|
|
@ -4,6 +4,7 @@ using N_m3u8DL_RE.Enum;
|
||||||
using System.CommandLine;
|
using System.CommandLine;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace N_m3u8DL_RE.Util
|
namespace N_m3u8DL_RE.Util
|
||||||
{
|
{
|
||||||
|
@ -94,6 +95,30 @@ namespace N_m3u8DL_RE.Util
|
||||||
return new TimeSpan(days, hours, mins, secs);
|
return new TimeSpan(days, hours, mins, secs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从1h3m20s解析出总秒数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timeStr"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ArgumentException"></exception>
|
||||||
|
public static double ParseSeconds(string timeStr)
|
||||||
|
{
|
||||||
|
var pattern = new Regex(@"^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$");
|
||||||
|
|
||||||
|
var match = pattern.Match(timeStr);
|
||||||
|
|
||||||
|
if (!match.Success)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("时间格式无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
int hours = match.Groups[1].Success ? int.Parse(match.Groups[1].Value) : 0;
|
||||||
|
int minutes = match.Groups[2].Success ? int.Parse(match.Groups[2].Value) : 0;
|
||||||
|
int seconds = match.Groups[3].Success ? int.Parse(match.Groups[3].Value) : 0;
|
||||||
|
|
||||||
|
return hours * 3600 + minutes * 60 + seconds;
|
||||||
|
}
|
||||||
|
|
||||||
//若该文件夹为空,删除,同时判断其父文件夹,直到遇到根目录或不为空的目录
|
//若该文件夹为空,删除,同时判断其父文件夹,直到遇到根目录或不为空的目录
|
||||||
public static void SafeDeleteDir(string dirPath)
|
public static void SafeDeleteDir(string dirPath)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue