private List <TsFileInfo> GetPieces(string hls_pl) { List <TsFileInfo> pieces = new List <TsFileInfo>(); TsFileInfo currInfo = new TsFileInfo() { name = null, size = 0 }; foreach (string line in hls_pl.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)) { if (IsValidLine(line)) { TsFileInfo tsInfo = GetInfoFromLine(line); if (tsInfo.name != currInfo.name) { // Starting a new TS file // If we are not at the first entry, list the piece if (currInfo.name != null) { pieces.Add(currInfo); } // Begin the new piece from our current line currInfo = tsInfo; } else { // Continuing an existing piece, only update end offset currInfo.end_offset = tsInfo.end_offset; currInfo.size += tsInfo.size; } } } pieces.Add(currInfo); return(pieces); }
private void MakeState(string url, string path) { // Get general info about the playlist string hls_pl = Encoding.UTF8.GetString(DownloadDataSafe(url)); string hls_base = url.Remove(url.LastIndexOf('/') + 1); List <TsFileInfo> pieces = GetPieces(hls_pl); // Run over the file long size = new FileInfo(path).Length; long cur_pos = 0; int i = 0; for (i = 0; i < pieces.Count; i++) { TsFileInfo piece = pieces[i]; int cur_size = 1 + GetOffset(piece.end_offset) - GetOffset(piece.start_offset); if (cur_pos + cur_size <= size) { cur_pos += cur_size; } else { break; } } if (i == pieces.Count) { MessageBox.Show("File is complete"); } else { File.WriteAllBytes(pieces[i - 1].name, DownloadDataUberSafe(pieces[i - 1].MakeUrl(hls_base))); SaveState(i, cur_pos); MessageBox.Show("Saved state"); } }
private void DownloadPlaylist(string url, string outdir, string id, double ratio, double eratio) { // Get general info about the playlist string hls_pl = Encoding.UTF8.GetString(DownloadDataSafe(url)); string hls_base = url.Remove(url.LastIndexOf('/') + 1); List <TsFileInfo> pieces = GetPieces(hls_pl); // Start GUI features (progressbar and download speed) InitProgress(pieces.Count); Stopwatch sw = new Stopwatch(); sw.Start(); long totBytes = 0; // We now have all pieces and need to just download and concat them string tspath = Path.Combine(outdir, id + ".ts"); int i_start = 0; long pos = 0; // If there is a backup, try to restore if (File.Exists(StateFileName) && MessageBox.Show("Restore backup?", "Backup", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { int[] data = File.ReadAllLines(StateFileName).Select(x => int.Parse(x)).ToArray(); i_start = data[0]; pos = data[1]; } else { i_start = GetBytePieceIndex(pieces, ratio); } int i_end = GetBytePieceIndex(pieces, eratio) + 1; Log(string.Format("Fast tracked to piece {0}, ending at {1}/{2}", i_start, i_end, pieces.Count)); // Actual DL using (FileStream fs = new FileStream(tspath, pos == 0 ? FileMode.Create : FileMode.Open)) { if (pos != 0) { fs.Seek(pos, SeekOrigin.Begin); } for (int i = 0; i < i_start; i++) { AdvanceProgress(); } for (int i = i_start; i < i_end; i++) { // Backup our progress SaveState(i, fs.Position); // Download the data TsFileInfo tsInfo = pieces[i]; sw.Restart(); byte[] data = DownloadDataUberSafe(tsInfo.MakeUrl(hls_base)); // Write to file, log and do GUI features totBytes /*+*/ = data.Length; Log("Writing " + data.Length.ToString() + " bytes to position " + fs.Position.ToString()); fs.Write(data, 0, data.Length); AdvanceProgress(); SetSpeed(totBytes / 1024.0 / 1024.0 / sw.Elapsed.TotalSeconds); Thread.Sleep(sleep); } } // Remove backup file since we finished File.Delete(StateFileName); // Encoding Log("FFMPEG"); string mp4path = Path.Combine(outdir, id + ".mp4"); if (File.Exists(mp4path)) { new FileInfo(mp4path).Delete(); } Process.Start("ffmpeg", "-i " + tspath + " -acodec copy -vcodec copy -bsf:a aac_adtstoasc " + mp4path); Log("Done."); }