Register Register Member Login Member Login Member Login Forgot Password ??
PHP , ASP , ASP.NET, VB.NET, C#, Java , jQuery , Android , iOS , Windows Phone
 

Registered : 108,597

HOME > .NET Framework > Forum > ช่วยหาแนวทางให้หน่อยครับ ผมอยากให้มันทำงาน รอบเดียวจบ ครับ



 

ช่วยหาแนวทางให้หน่อยครับ ผมอยากให้มันทำงาน รอบเดียวจบ ครับ

 



Topic : 135688



โพสกระทู้ ( 4,172 )
บทความ ( 23 )



สถานะออฟไลน์
Facebook



โค้ด ต้นฉบับ นะครับ
https://github.com/bertyhell/PlaylistDownloader/blob/master/PlaylistDownloader/PlaylistDownloader/Downloader.cs


ผมอยากให้รัน YoutubeDl แล้ว ต่อด้วย Ffmpeg ให้เสร็จก่อน แล้วจึงค่อยรันไฟล์ใหม่ ครับ
โค้ดต้นฉบับ รันทุกไฟล์พร้อมๆกันทั้งหมดทำให้เครื่องช้า ครับ



Tag : .NET, Win (Windows App), C#







Move To Hilight (Stock) 
Send To Friend.Bookmark.
Date : 2020-11-03 16:32:32 By : lamaka.tor View : 145 Reply : 7
 

 

No. 1



โพสกระทู้ ( 8,898 )
บทความ ( 2 )



สถานะออฟไลน์


Code (C#)
int count_run_1 = 0;
int count_run_2 = 0;
function run1(id){
  // do something
  count_run_1--;
  if( count_run_1<1){
    loop_run2();
  }
}
function loop_run2(){
  for( i = 0 ; i < 10 ; i++){
    count_run_1++; 
    async run1( i );
  }
}
for( i = 0 ; i < 10 ; i++){
  count_run_1++; 
  async run1( i );
}


แค่ตัวอย่าง ง่ายๆ ของ การกำหนด การ run แบบ asyn เป็นชุด syn
ไม่ต้องสนไวยกรณ์ นะครับ ลืมหมดแล้ว ช่วงไม่มีงาน visual ก็ส่งกลับเข้า หนังสือ เข้าเวป หมด 5555
ไว้ต้องเขียน ค่อยรื้อมาใหม่






แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2020-11-04 11:32:18 By : Chaidhanan
 


 

No. 2



โพสกระทู้ ( 4,172 )
บทความ ( 23 )



สถานะออฟไลน์
Facebook

ตอบความคิดเห็นที่ : 1 เขียนโดย : Chaidhanan เมื่อวันที่ 2020-11-04 11:32:18
รายละเอียดของการตอบ ::
ผมลองดักทุกทาง แล้วก็ไม่ช่วยอะไรได้เลยครับ

ปัญหามันอยู่ที่การทำงานร่วมกับไฟล์ YoutubeDl และ Ffmpeg มันส่งค่ากลับมาเพื่อให้เช็คว่างานเสร็จ หรือไม่เสร็จ แล้วมันไม่ตรง ครับ
มันจึงกลายเป็นว่า ถึงแม้ งานจะไม่เสร็จ 100 % แต่มันก็ยังทำงานอื่นต่อไปอีก ครับ


แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2020-11-04 14:51:32 By : lamaka.tor
 

 

No. 3



โพสกระทู้ ( 8,898 )
บทความ ( 2 )



สถานะออฟไลน์


ถ้าจำเป็น ต้องเสร็จ เพื่อ ทำงานต่อ ก็ต้อง ใช้ promise await แล้วล่ะครับ

จะให้มัน ทำงานแบบ asyncronize คงไม่ได้
แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2020-11-04 19:01:39 By : Chaidhanan
 


 

No. 4



โพสกระทู้ ( 4,172 )
บทความ ( 23 )



สถานะออฟไลน์
Facebook

ตอบความคิดเห็นที่ : 3 เขียนโดย : Chaidhanan เมื่อวันที่ 2020-11-04 19:01:39
รายละเอียดของการตอบ ::
ตัวนี้ผมก็ทำไปแล้วเช่นกันครับ
อย่างที่ผมบอกครับ

ปัญหามันอยู่ที่การทำงานร่วมกับไฟล์ YoutubeDl และ Ffmpeg มันส่งค่ากลับมาเพื่อให้เช็คว่างานเสร็จ หรือไม่เสร็จ แล้วมันไม่ตรง ครับ
มันจึงกลายเป็นว่า ถึงแม้ งานจะไม่เสร็จ 100 % แต่มันก็ยังทำงานอื่นต่อไปอีก ครับ

แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2020-11-04 19:56:56 By : lamaka.tor
 


 

No. 5



โพสกระทู้ ( 8,898 )
บทความ ( 2 )



สถานะออฟไลน์


https://stackoverflow.com/questions/10788982/is-there-any-async-equivalent-of-process-start
เพื่อจะได้ประโยชน์
แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2020-11-05 02:03:09 By : Chaidhanan
 


 

No. 6



โพสกระทู้ ( 4,172 )
บทความ ( 23 )



สถานะออฟไลน์
Facebook

ตอบความคิดเห็นที่ : 5 เขียนโดย : Chaidhanan เมื่อวันที่ 2020-11-05 02:03:09
รายละเอียดของการตอบ ::
ในโค้ดเดิม มันมีอยู่แล้วครับ
แล้วมันก็มีปัญหาตั้งแต่โค้ดเดิม เลยครับ
สั่งดาวน์โหลดปุ๊บ มันโหลดทั้งหมดในเวลาเดียวกันเลยครับ

ตอนนี้ผมเอามันออก แล้วใช้ task คุมทั้ง หมด ก็ค่อยยังชั่วขึ้นบ้าง
โหลดทีละไฟล์ ได้ แต่มันก็ยังมีบ้างที่ เหมือนว่า มัน รันไปใกล้จะครบ 100 % แล้ว
ไฟล์อื่นก็ทำงานต่อ แล้วก็ ทำงานต่อๆ กันไปอีก มากกว่า 2 ไฟล์ ทำให้เครื่องค้างเช่นกัน ครับ



แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2020-11-05 07:57:13 By : lamaka.tor
 


 

No. 7



โพสกระทู้ ( 4,172 )
บทความ ( 23 )



สถานะออฟไลน์
Facebook

โค้ดเดิม มันจะได้แบบนี้ครับ
1

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;

namespace PlaylistDownloader
{
    public class Downloader : BackgroundWorker
    {

        private readonly ICollection<PlaylistItem> _playlist;
        private readonly RunSettings _runSettings;
        public double progressValue = 0d;
        private int _progress;
        private readonly int _totalSongs;
        private CancellationTokenSource _cts;
        private static Logger logger = LogManager.GetCurrentClassLogger();

        public Downloader(RunSettings settings, ICollection<PlaylistItem> playlist)
        {
            _playlist = playlist;
            _totalSongs = _playlist.Count;

            _cts = new CancellationTokenSource();

            _runSettings = settings;
        }

        protected override void OnDoWork(DoWorkEventArgs args)
        {
            _progress = 0;

            //setup cancelation
            ParallelOptions po = new ParallelOptions
            {
                CancellationToken = _cts.Token,
                MaxDegreeOfParallelism = Environment.ProcessorCount
            };

            try
            {
                // Parallal execution
                try
                {
                    Parallel.ForEach(_playlist, po, async item =>
                    {
                        try
                        {
                            po.CancellationToken.ThrowIfCancellationRequested();
                            await DownloadPlaylistItem(item);
                        }
                        catch (InvalidOperationException) { } //ignore exceptions when aborting download
                        catch (Win32Exception) { } //ignore process exception if killed during process exiting
                    });
                }
                catch (OperationCanceledException) { }
                finally
                {
                    if (_cts != null)
                    {
                        _cts.Dispose();
                        _cts = null;
                    }
                }
                // Serial execution
                //foreach (PlaylistItem item in _playlist)
                //{
                //    try
                //    {
                //        DownloadPlaylistItem(item, po);
                //        //ConvertPlaylistItem(item, po);
                //    }
                //    catch (InvalidOperationException) { } //ignore exceptions when aborting download
                //    catch (Win32Exception) { } //ignore process exception if killed during process exiting
                //}
            }
            catch (OperationCanceledException) { } //ignore exceptions caused by canceling paralel.foreach loop
        }

        public async Task<string> DownloadPlaylistItem(PlaylistItem item)
        {
            string destinationFilePathWithoutExtension = null;
            string tempFilePathWithoutExtension = null;

            item.DownloadProgress = 5;
            if (!string.IsNullOrWhiteSpace(item.FileName))
            {

               
                var workingFolder = Path.GetTempPath();
                tempFilePathWithoutExtension = Path.Combine(Path.GetTempPath(), item.FileName);
                destinationFilePathWithoutExtension = Path.Combine(_runSettings.SongsFolder, item.FileName);

                if (!File.Exists(destinationFilePathWithoutExtension + ".mp3"))
                {
                    item.DownloadProgress = 10;

                   
                        // Download videoand extract the mp3 file
                        await StartProcess(
                            _runSettings.YoutubeDlPath,
                            string.Format(" --ffmpeg-location \"{0}\"" +
                                          " --format bestaudio[ext=mp3]/best" +
                                          " --audio-quality 0" +
                                          " --no-part" +
                                          " --extract-audio" +
                                          " --audio-format mp3" +
                                          " --output \"{1}\"" +
                                          " {2}", _runSettings.FfmpegPath, tempFilePathWithoutExtension + "-raw.%(ext)s", item.Link),
                            item,
                            ParseYoutubeDlProgress);
                        // -o "c:\Users\Julian\Music\PlaylistDownloader\\%(title)s.%(ext)s"

                        // Normalize audio file after the youtube-dl process has exited
                        await StartProcess(_runSettings.FfmpegPath,
                            string.Format(" -i \"{0}\"" +
                                          " -af loudnorm=I=-16:TP=-1.5:LRA=11" +
                                          //" -ar 48k" +
                                          " -y" +
                                          " \"{1}\"", tempFilePathWithoutExtension + "-raw.mp3", tempFilePathWithoutExtension + _runSettings.NormalizedSuffix + ".mp3"),
                            item,
                            ParseYoutubeDlProgress);

                        // move to destination
                        File.Move(tempFilePathWithoutExtension + _runSettings.NormalizedSuffix + ".mp3",
                            destinationFilePathWithoutExtension + _runSettings.NormalizedSuffix + ".mp3");

                        // Delete the non normalized file after completion if not in debug mode
                        File.Delete(Path.Combine(_runSettings.SongsFolder, item.FileName + "-raw.mp3"));
                    


                }
            }

            item.DownloadProgress = 100;
            _progress++;
            OnProgressChanged(new ProgressChangedEventArgs(_progress * 100 / _totalSongs, null));
            progressValue = Convert.ToDouble(((double)_progress * 100d / (double)_totalSongs).ToString("N2"));


            return destinationFilePathWithoutExtension;
        }

        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 = (int)(10.0 + downloadProgress / 100 * 60);
                    OnProgressChanged(new ProgressChangedEventArgs(_progress * 100 / _totalSongs, null));
                }
            }
        }

        private void ParseNormalizeProgress(string consoleLine, PlaylistItem item)
        {
            // Duration: 00:30:58.39, start: 0.023021, bitrate: 106 kb/s
            // size=     105kB time=00:00:06.69 bitrate= 128.7kbits/s speed=13.4x 
            Regex extractDuration = new Regex(@"Duration:\s*([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{2}),\sstart:");
            Match match = extractDuration.Match(consoleLine);
            if (match.Length > 0 && match.Groups.Count >= 2)
            {
                logger.Info("Duration: " + match.Groups[0].Value);
                item.Duration = TimeSpan.Parse(match.Groups[0].Value).TotalSeconds;
                logger.Info("Duration seconds: " + item.Duration);
                return;
            }

            if (item.Duration == 0)
            {
                return;
            }

            Regex extractProgressDuration = new Regex(@"time=([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{2})\s*bitrate=");
            match = extractProgressDuration.Match(consoleLine);
            if (match.Length > 0 && match.Groups.Count >= 2)
            {
                logger.Info("progress Duration: " + match.Groups[0].Value);
                logger.Info("progress Duration seconds: " + TimeSpan.Parse(match.Groups[0].Value).TotalSeconds);
                item.DownloadProgress = (int)(70 + TimeSpan.Parse(match.Groups[0].Value).TotalSeconds / item.Duration * 30);
                OnProgressChanged(new ProgressChangedEventArgs(_progress * 100 / _totalSongs, null));
            }
        }

        private Task<string> StartProcess(string executablePath, string arguments, PlaylistItem item, Action<string, PlaylistItem> parseProgressFunc)
        {
            var promise = new TaskCompletionSource<string>();
            logger.Info("[RUN CMD] " + executablePath + arguments);
            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);
                }
            };

            process.Exited += new EventHandler((object sender, EventArgs e) =>
            {
                process.Dispose();
                logger.Info("Closing process");
                promise.SetResult(null);
            });

            process.Start();

            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            return promise.Task;
        }

        internal void Abort()
        {
            if (_cts != null)
            {
                _cts.Cancel();
                _cts = null;
            }
            CancelAsync();
        }

        private static string MakeValidFileName(string name)
        {
            return Regex.Replace(
                name,
                "[^A-Za-z0-9_ -]+",  /*Matches any nonword character. Equivalent to '[^A-Za-z0-9_]'*/
                "-",
                RegexOptions.IgnoreCase).Trim('-', ' ').ToLower();
        }
    }
}


โค้ดที่ปรับแต่งแล้วได้ประมาณนี้ครับ

2

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;

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;
        public Downloader(RunSettings settings, ICollection<PlaylistItem> playlist)
        {
            _playlist = playlist.ToList<PlaylistItem>();
            _totalSongs = _playlist.Count;

            _cts = new CancellationTokenSource();

            _runSettings = settings;
        }
        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 =>
            {
                tasks.Add(factory.StartNew(() => DownloadPlaylistItem(plst)));
            });

            Task.WaitAll(tasks.ToArray());


        }

        public void DownloadPlaylistItem(PlaylistItem item)
        {
            string destinationFilePathWithoutExtension = null;
             string tempFilePathWithoutExtension = null;

            item.DownloadProgress = 5;
            if (!string.IsNullOrWhiteSpace(item.FileName) )
            {
                tempFilePathWithoutExtension = Path.Combine(_runSettings.FolTemp, MakeValidFileName(item.FileName)) ;
                destinationFilePathWithoutExtension = Path.Combine(_runSettings.SongsFolder + "\\" + MakeValidFileName(item.OwnerName), MakeValidFileName(item.FileName)) ;
                item.DownloadProgress = 10;
                if (!File.Exists(destinationFilePathWithoutExtension) || !File.Exists(tempFilePathWithoutExtension))
                {
                  StartProcessyoutube_dl(item, tempFilePathWithoutExtension, destinationFilePathWithoutExtension,ParseYoutubeDlProgress);
                }
                else
                {
                    Finish(item);
                }
            }
            else
            {
                Finish(item);

            }


        }
     
        private string StartProcessyoutube_dl( PlaylistItem item, string tempFile, string desFile, Action<string, PlaylistItem> parseProgressFunc)
        {
            string executablePath = _runSettings.YoutubeDlPath;
            string destinationFilePathWithoutExtension = desFile;
            string tempFilePathWithoutExtension = tempFile;
            var promise = new TaskCompletionSource<string>();

            Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePathWithoutExtension));

            string arguments = string.Format(" --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);
                Finish(item);
                /* if (File.Exists(tempFilePathWithoutExtension + ".mp4"))
                 { 
                  if(new FileInfo(tempFilePathWithoutExtension + ".mp4").Length>0)
                 StartProcessffmpeg(item, tempFilePathWithoutExtension , destinationFilePathWithoutExtension, ParseYoutubeDlProgress);
                 }*/



            });

            process.Start();

            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            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 * 90);

                    OnProgressChanged(new ProgressChangedEventArgs(_progress * 100 / _totalSongs, null));

                }
            }
        }


        public void Finish(PlaylistItem item)
        {
            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]);
                /*if(File.Exists(tempFilePathWithoutExtension + ".mp4"))
                File.Delete(tempFilePathWithoutExtension + ".mp4");*/
            }
            catch { }


        }
        internal void Abort()
        {
            if (_cts != null)
            {
                _cts.Cancel();
                _cts = null;
            }
            CancelAsync();
        }

        private static string MakeValidFileName(string name)
        {
            /* return Regex.Replace(
                 name,
                 "[^A-Za-z0-9_ -]+",  /*Matches any nonword character. Equivalent to '[^A-Za-z0-9_]'*
                 "-",
                 RegexOptions.IgnoreCase).Trim('-', ' ').ToLower();*/

            return new Regex(@"([~\""#%&*:<>?/\{|}\]\[\.]{1,})", RegexOptions.None).Replace(name, "");
        }

    }
}





ปล.ไม่ทราบว่ามีใคร มี โค้ดดาวน์โหลดไฟล์ยูทูปไม๊ ครับ ที่ไม่ใช่ youtube-dl ครับ
แสดงความคิดเห็นโดยอ้างถึง ความคิดเห็นนี้
Date : 2020-11-05 08:43:32 By : lamaka.tor
 

   

ค้นหาข้อมูล


   
 

แสดงความคิดเห็น
Re : ช่วยหาแนวทางให้หน่อยครับ ผมอยากให้มันทำงาน รอบเดียวจบ ครับ
 
 
รายละเอียด
 
ตัวหนา ตัวเอียง ตัวขีดเส้นใต้ ตัวมีขีดกลาง| ตัวเรืองแสง ตัวมีเงา ตัวอักษรวิ่ง| จัดย่อหน้าอิสระ จัดย่อหน้าชิดซ้าย จัดย่อหน้ากึ่งกลาง จัดย่อหน้าชิดขวา| เส้นขวาง| ขนาดตัวอักษร แบบตัวอักษร
ใส่แฟลช ใส่รูป ใส่ไฮเปอร์ลิ้งค์ ใส่อีเมล์ ใส่ลิ้งค์ FTP| ใส่แถวของตาราง ใส่คอลัมน์ตาราง| ตัวยก ตัวห้อย ตัวพิมพ์ดีด| ใส่โค้ด ใส่การอ้างถึงคำพูด| ใส่ลีสต์
smiley for :lol: smiley for :ken: smiley for :D smiley for :) smiley for ;) smiley for :eek: smiley for :geek: smiley for :roll: smiley for :erm: smiley for :cool: smiley for :blank: smiley for :idea: smiley for :ehh: smiley for :aargh: smiley for :evil:
Insert PHP Code
Insert ASP Code
Insert VB.NET Code Insert C#.NET Code Insert JavaScript Code Insert C#.NET Code
Insert Java Code
Insert Android Code
Insert Objective-C Code
Insert XML Code
Insert SQL Code
Insert Code
เพื่อความเรียบร้อยของข้อความ ควรจัดรูปแบบให้พอดีกับขนาดของหน้าจอ เพื่อง่ายต่อการอ่านและสบายตา และตรวจสอบภาษาไทยให้ถูกต้อง

อัพโหลดแทรกรูปภาพ

Notice

เพื่อความปลอดภัยของเว็บบอร์ด ไม่อนุญาติให้แทรก แท็ก [img]....[/img] โดยการอัพโหลดไฟล์รูปจากที่อื่น เช่นเว็บไซต์ ฟรีอัพโหลดต่าง ๆ
อัพโหลดแทรกรูปภาพ ให้ใช้บริการอัพโหลดไฟล์ของไทยครีเอท และตัดรูปภาพให้พอดีกับสกรีน เพื่อความโหลดเร็วและไฟล์ไม่ถูกลบทิ้ง

   
  เพื่อความปลอดภัยและการตรวจสอบ กระทู้ที่แทรกไฟล์อัพโหลดไฟล์จากที่อื่น อาจจะถูกลบทิ้ง
 
โดย
อีเมล์
บวกค่าให้ถูก
<= ตัวเลขฮินดูอารบิก เช่น 123 (หรือล็อกอินเข้าระบบสมาชิกเพื่อไม่ต้องกรอก)







Exchange: Voake, Comcube, รับทำเว็บไซต์ รับเขียนโปรแกรม , pangpond.com , pangpond.co.th , สำนักงานบัญชี.com , รถมือสอง

Load balance : Server 05
ThaiCreate.Com Logo
© www.ThaiCreate.Com. 2003-2021 All Rights Reserved.
ไทยครีเอทบริการ จัดทำดูแลแก้ไข Web Application ทุกรูปแบบ (PHP, .Net Application, VB.Net, C#)
[Conditions Privacy Statement] ติดต่อโฆษณา 081-987-6107 อัตราราคา คลิกที่นี่