/// <summary> /// 立即开始录播任务 /// </summary> public static async void LaunchRecording(RecordSchedule schedule) { // 获取视频片段长度 HttpClient client = new HttpClient(); var m3u = await client.GetStringAsync(schedule.PlaylistUri); client.Dispose(); const string tag = "#EXT-X-TARGETDURATION"; var tag_index = m3u.IndexOf(tag) + tag.Length + 1; string interval = m3u.Substring(tag_index, m3u.IndexOf('\n', tag_index) - tag_index); schedule.SegmentLength = TimeSpan.FromSeconds(double.Parse(interval)); // 创建下载任务 await schedule.GenerateDownloadTask(); schedule.Status = ScheduleStatus.Downloading; }
/// <summary> /// 开始录播计划任务,定时开始下载 /// </summary> /// <param name="schedule">任务对象</param> public static async void LaunchSchedule(RecordSchedule schedule) { // 获取后台运行权限,这个感觉不是必要的? var status = await BackgroundExecutionManager.RequestAccessAsync(); if (status == BackgroundAccessStatus.Unspecified || status == BackgroundAccessStatus.Denied) { // TODO: 权限被拒绝,需要提示用户 return; } var key = schedule.Key; Guid taskId; var builder = ScheduleTask.CreateBackgroundTaskBuilder( out taskId, schedule.StartTime.Subtract(DateTimeOffset.Now)); Container.Values[key] = taskId; }
// TODO: 后台定时器有15分钟的误差,因此若需准确开始需要提前15分钟 public async void Run(IBackgroundTaskInstance taskInstance) { // 寻找对应的下载计划 RecordSchedule schedule = null; foreach (var item in RecordScheduleManager.Container.Values) { if ((Guid)item.Value == taskInstance.Task.TaskId) { schedule = new RecordSchedule(item.Key); } } if (schedule == null) { System.Diagnostics.Debug.WriteLine("未找到对应的下载计划", "Error"); return; } if (schedule.Status == ScheduleStatus.Terminated) { System.Diagnostics.Debug.WriteLine("下载计划被终止"); return; } var _defer = taskInstance.GetDeferral(); // 生成下一个下载,若下载完毕则直接处理文件 schedule.Status = ScheduleStatus.Downloading; var operation = await schedule.GenerateDownloadTask(); if (operation == null) { // TODO: 什么情况下会发生? System.Diagnostics.Debugger.Break(); schedule.Status = ScheduleStatus.Completed; } _defer.Complete(); }
/// <summary> /// 创建新的录播计划 /// </summary> /// <param name="identifier">标识名,每一个下载任务不应相同</param> /// <param name="playlistUri">直播文件的地址</param> /// <param name="startTime">开始录播的时间</param> /// <param name="recordSpan">录播时长</param> public static RecordSchedule CreateSchedule( string identifier, string playlistUri, DateTimeOffset startTime, TimeSpan recordSpan) { var key = EncodeIndentifier(identifier); // 这里直接同步运行以避免async传染 var video = Async.InvokeAndWait(async() => await StorageLibrary.GetLibraryAsync(KnownLibraryId.Videos)); object path = null; ApplicationData.Current.LocalSettings.Values.TryGetValue("RecordingPath", out path); var pathstr = path?.ToString(); var filepath = (string.IsNullOrWhiteSpace(pathstr) ? video.SaveFolder.Path : pathstr) + '\\' + identifier + ".ts"; var schedule = new RecordSchedule(key) { PlaylistUri = playlistUri, StartTime = startTime, ScheduleSpan = recordSpan, Status = ScheduleStatus.Scheduled, SavePath = filepath }; RecordScheduleMessager.Instance.Trigger(key, RecordScheduleMessageType.Created); return(schedule); }
/// <summary> /// 删除下载计划的记录 /// </summary> /// <param name="schedule">下载计划对象</param> public static void DeleteSchedule(RecordSchedule schedule) { Container.DeleteContainer(schedule.Key); Container.Values.Remove(schedule.Key); RecordScheduleMessager.Instance.Trigger(schedule.Key, RecordScheduleMessageType.Deleted); }
/// <summary> /// 终止下载计划 /// </summary> public static void TerminateSchedule(RecordSchedule schedule) => schedule.Status = ScheduleStatus.Terminated;
public async void Run(IBackgroundTaskInstance taskInstance) { var details = taskInstance.TriggerDetails as BackgroundTransferCompletionGroupTriggerDetails; if (details == null) { System.Diagnostics.Debug.WriteLine("下载任务非下载完成后触发", "Error"); return; } // 寻找对应的下载计划 RecordSchedule schedule = null; foreach (var item in RecordScheduleManager.Container.Values) { if ((Guid)item.Value == taskInstance.Task.TaskId) { schedule = new RecordSchedule(item.Key); } } if (schedule == null) { System.Diagnostics.Debug.WriteLine("未找到对应的下载计划", "Error"); return; } if (details.Downloads.Any(op => IsFailed(op))) { // 下载失败 schedule.Status = ScheduleStatus.Failed; // 生成下载失败的消息提醒 XmlDocument failedToastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01); failedToastXml.GetElementsByTagName("text").Item(0).InnerText = "一项录播任务失败"; ToastNotification failedToast = new ToastNotification(failedToastXml); ToastNotificationManager.CreateToastNotifier().Show(failedToast); return; } RecordScheduleMessager.Instance.Trigger(schedule.Key, RecordScheduleMessageType.DownloadedOne); var _defer = taskInstance.GetDeferral(); if (schedule.Status == ScheduleStatus.Terminated) { System.Diagnostics.Debug.WriteLine("下载计划被终止"); // 将已下载的缓存合并成文件保存下来 schedule.Status = ScheduleStatus.Decoding; var continuous = await schedule.ConcatenateSegments(schedule.SavePath); schedule.Status = ScheduleStatus.Terminated; return; } // 生成下一个下载,若下载完毕则直接处理文件 var operation = await schedule.GenerateDownloadTask(); if (operation == null) { schedule.Status = ScheduleStatus.Decoding; var continuous = await schedule.ConcatenateSegments(schedule.SavePath); // 生成下载成功的消息提醒 XmlDocument successToastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01); successToastXml.GetElementsByTagName("text").Item(0).InnerText = "一项录播任务已经成功结束" + (continuous ? string.Empty : ",但可能录播不完整。"); ToastNotification successToast = new ToastNotification(successToastXml); ToastNotificationManager.CreateToastNotifier().Show(successToast); } _defer.Complete(); }