|
|
|
C# Error แบบนี้ แก้ยังไงครับ (จะเช็คการสิ้นสุดการทำงานของ youtube_dl.exe ครับ) |
|
|
|
|
|
|
|
ตันฉบับโค้ด
https://markheath.net/post/how-to-get-media-file-duration-in-c
คือ ผมจะ Do while จนกว่า จะมีค่า duration เวลา ดาวน์โหลด ครับ
หรือใครมีวิธีเช็ค การสิ้นสุดการดาวน์โหลด ของ youtube_dl.exe ไม๊ ครับ ว่าจะเช็คยังไง
ผมลองใช้ process.Exited ดักแล้วก็ยังไม่ได้ครับ
Code (C#)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using NLog;
using TorServices;
using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;
namespace PlaylistDownloader
{
//https://github.com/bertyhell/PlaylistDownloader/blob/master/PlaylistDownloader/PlaylistDownloader/Downloader.cs
public class Downloader : BackgroundWorker
{
private readonly List<PlaylistItem> _playlist;
private readonly RunSettings _runSettings;
private int _progress;
private int _totalSongs;
private int _completeSongs;
private CancellationTokenSource _cts;
private static Logger logger = LogManager.GetCurrentClassLogger();
public double progressValue = 0d;
private bool ConverttoMP3;
public Downloader(RunSettings settings, ICollection<PlaylistItem> playlist,bool converttomp3)
{
_playlist = playlist.ToList<PlaylistItem>();
_totalSongs = _playlist.Count;
_cts = new CancellationTokenSource();
_runSettings = settings;
ConverttoMP3 = converttomp3;
}
int itemIndex = 0;
protected override void OnDoWork(DoWorkEventArgs args)
{
_progress = 0;
// LimitedConcurrencyLevelTaskScheduler scheduler = new LimitedConcurrencyLevelTaskScheduler(1);
// var factory = new TaskFactory(scheduler);
// var tasks = new List<Task>();
_playlist.ForEach(plst =>
{
DownloadPlaylistItem(plst);
// tasks.Add(factory.StartNew(() => DownloadPlaylistItem(plst)));
});
// Task.WaitAll(tasks.ToArray());
}
//https://markheath.net/post/how-to-get-media-file-duration-in-c
TimeSpan GetDuration(string filePath)
{
using (var shell = ShellObject.FromParsingName(filePath))
{
IShellProperty prop = shell.Properties.System.Media.Duration;
var t = (ulong)prop.ValueAsObject;
return TimeSpan.FromTicks((long)t);
}
}
public void DownloadPlaylistItem(PlaylistItem item)
{
string destinationFilePathWithoutExtension = null;
// string tempFilePathWithoutExtension = null;
item.DownloadProgress = 5;
if (!string.IsNullOrWhiteSpace(item.FileName))
{
// tempFilePathWithoutExtension = Path.Combine(_runSettings.FolTemp, item.FileName.MakeValidFileName());
destinationFilePathWithoutExtension = Path.Combine(_runSettings.SongsFolder, item.FileName.MakeValidFileName()) ;
item.DownloadProgress = 10;
if (!File.Exists(destinationFilePathWithoutExtension + ".mp4"))
{
StartProcessyoutube_dl(item, destinationFilePathWithoutExtension, ParseYoutubeDlProgress);
}
else
{
Finish(item, destinationFilePathWithoutExtension);
}
}
else
{
Finish(item, destinationFilePathWithoutExtension);
}
}
private string StartProcessyoutube_dl(PlaylistItem item, string desFile, Action<string, PlaylistItem> parseProgressFunc)
{
string executablePath = _runSettings.YoutubeDlPath;
string destinationFilePathWithoutExtension = desFile;
var promise = new TaskCompletionSource<string>();
string arguments = string.Format( " --audio-quality 0 --no-part --output \"{0}\" {1}", destinationFilePathWithoutExtension + ".mp4", item.Link);
logger.Info("[RUN CMD] " + executablePath + arguments);
string _filename = executablePath;
Process process = new Process
{
StartInfo =
{
FileName = executablePath,
Arguments = arguments,
CreateNoWindow = !_runSettings.IsDebug,
WindowStyle = _runSettings.IsDebug ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
},
EnableRaisingEvents = true
};
// --audio-quality 5 --extract-audio --audio-format mp3 -o "c:\Users\Julian\Music\PlaylistDownloader\\%(title)s.%(ext)s" https://www.youtube.com/watch?v=mDuElaL1dU0
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
{
string consoleLine = e.Data;
if (!string.IsNullOrWhiteSpace(consoleLine))
{
logger.Info(consoleLine);
parseProgressFunc(consoleLine, item);
}
if (CancellationPending)
{
logger.Info("Canceling process because of user: " + executablePath);
process.Close();
promise.SetResult(null);
}
};
process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
{
string consoleLine = e.Data;
if (!string.IsNullOrWhiteSpace(consoleLine))
{
logger.Info("Error: " + consoleLine);
parseProgressFunc(consoleLine, item);
}
if (CancellationPending)
{
logger.Info("Canceling process because of user: " + executablePath);
process.Close();
promise.SetResult(null);
}
// Finish(item, tempFilePathWithoutExtension);
};
process.Exited += new EventHandler((object sender, EventArgs e) =>
{
process.Dispose();
logger.Info("Closing process");
promise.SetResult(null);
if (File.Exists(destinationFilePathWithoutExtension + ".mp4"))
{
if (new FileInfo(destinationFilePathWithoutExtension + ".mp4").Length > 0)
{
Thread.Sleep(1000);
if (ConverttoMP3)
{
if (!System.IO.File.Exists(destinationFilePathWithoutExtension + ".mp3"))
{
StartProcessffmpeg(item, destinationFilePathWithoutExtension);
}
else
{
Finish(item, destinationFilePathWithoutExtension);
}
}
else
{
Finish(item, destinationFilePathWithoutExtension);
}
//Finish(item, destinationFilePathWithoutExtension);
//
}
}
});
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
/* do
{
Thread.Sleep(1000);
} while (!File.Exists(destinationFilePathWithoutExtension + ".mp4") || new FileInfo(destinationFilePathWithoutExtension + ".mp4").Length < 20000);
*/
do
{
Thread.Sleep(1000);
} while ( GetDuration(destinationFilePathWithoutExtension + ".mp4").TotalMinutes <= 0);
if (ConverttoMP3)
{
if (!System.IO.File.Exists(destinationFilePathWithoutExtension + ".mp3"))
{
StartProcessffmpeg(item, destinationFilePathWithoutExtension);
}
else
{
Finish(item, destinationFilePathWithoutExtension);
}
}
else
{
Finish(item, destinationFilePathWithoutExtension);
}
return promise.Task.Result;
}
private string StartProcessffmpeg(PlaylistItem item, string desFile)
{
string executablePath = _runSettings.FfmpegPath;
string destinationFilePathWithoutExtension = desFile;
var promise = new TaskCompletionSource<string>();
string arguments = string.Format(" -i \"{0}\" -b:a 192K -vn \"{1}\"", destinationFilePathWithoutExtension + ".mp4", destinationFilePathWithoutExtension + ".mp3");
logger.Info("[RUN CMD] " + executablePath + arguments);
string _filename = executablePath;
Process process = new Process
{
StartInfo =
{
FileName = executablePath,
Arguments = arguments,
CreateNoWindow = !_runSettings.IsDebug,
WindowStyle = _runSettings.IsDebug ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false
},
EnableRaisingEvents = true
};
process.Exited += new EventHandler((object sender, EventArgs e) =>
{
process.Dispose();
logger.Info("Closing process");
promise.SetResult(null);
Finish(item, destinationFilePathWithoutExtension);
});
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
do
{
Thread.Sleep(1000);
} while (GetDuration(destinationFilePathWithoutExtension + ".mp3").TotalMinutes <= 0);//new FileInfo(destinationFilePathWithoutExtension + ".mp3").Length < 1000
Thread.Sleep(3000);
File.Delete(destinationFilePathWithoutExtension + ".mp4");
Thread.Sleep(2000);
Finish(item, destinationFilePathWithoutExtension);
return promise.Task.Result;
}
private void ParseYoutubeDlProgress(string consoleLine, PlaylistItem item)
{
// [download] 0.0% of 4.66MiB at 336.14KiB/s ETA 00:14
Regex extractDownloadProgress = new Regex(@"\[download\][\s]*([0-9\.]+)%");
Match match = extractDownloadProgress.Match(consoleLine);
if (match.Length > 0 && match.Groups.Count >= 2)
{
if (double.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out double downloadProgress))
{
logger.Info("[download + convert progress] " + downloadProgress);
if (downloadProgress > 100)//|| _progress > 100
{
Debugger.Break();
}
item.DownloadProgress = (double)(10.0 + downloadProgress / 100 * 60);
OnProgressChanged(new ProgressChangedEventArgs(_progress * 100 / _totalSongs, null));
}
}
}
public void Finish(PlaylistItem item,string destinationFile)
{
item.DownloadProgress = 100;
itemIndex++;
_progress++;
progressValue = Convert.ToDouble(((double)_progress * 100d / (double)_totalSongs).ToString("N2"));
OnProgressChanged(new ProgressChangedEventArgs(_progress * 100 / _totalSongs, null));
try
{
if (itemIndex < _playlist.Count)
DownloadPlaylistItem(_playlist[itemIndex]);
}
catch { }
}
internal void Abort()
{
if (_cts != null)
{
_cts.Cancel();
_cts = null;
}
CancelAsync();
}
}
}
Tag : .NET, C#
|
|
|
|
|
|
Date :
2021-03-09 23:04:29 |
By :
lamaka.tor |
View :
823 |
Reply :
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ก็เห็นชัดเจนอยู่แล้วว่า filepath มีปัญหา (ด้วยข้อจำกัดของ Windows) อทิเช่น
- ยาวเกินไป เราเจอบ่อยมากฯ เล่นกับ .NET 6 ก็เจอเหมือนกัน
- อักขระพิเศษ เช่น Copy ไฟล์มาจาก จีน (ไม่รู้ว่าทำไมมันไม่ Save As BOM)
- มันแปลกฯ ทั้งฯที่สมัยก่อนจำได้ว่า มันมีกฏการตั้งชื่อไฟล์ ปัจจุบันมันเลือนลางไปแล้ว (ไม่มีใครพูดถึงกัน)
etc..
ไหนฯก็ไหนฯ คิดจะก้าวไปข้างหน้า .NET Core 3.1 --> .NET 6 + แม่งเลย
(ดู Flutter 2.0 เทียบกัน บรรทัดต่อบรรทัด)
|
|
|
|
|
Date :
2021-03-11 09:56:00 |
By :
ผ่านมา |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
เรายังจำได้ ว่า บางคนเคยโพสต์ Webform1.aspx, 2, 3, 4, .aspx
เห็นครั้งสุดท้ายจำได้แค่ว่า หลายปีมาแล้ว
ไม่ใช่อะไรหรอก กำลังจะบอกว่า ความรู้(อหังการ)ของคนพวกนี้ ไม่ไปไหนเลยนะ ย่ำอยู่กับที่
กินบุญเก่า และคิดว่า ตัวเองสำคัญ
|
|
|
|
|
Date :
2021-03-11 10:08:30 |
By :
ผ่านมา |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
https://github.com/ytdl-org/youtube-dl/issues/7120
ปล. ใช้คำค้น
youtube_dl.exe callback after finish
|
ประวัติการแก้ไข 2021-03-11 19:04:55
|
|
|
|
Date :
2021-03-11 19:03:04 |
By :
Chaidhanan |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Load balance : Server 04
|