private async void CreateOverlays() { var baseVideoClip = await MediaClip.CreateFromFileAsync(baseVideoFile); composition = new MediaComposition(); composition.Clips.Add(baseVideoClip); var overlayVideoClip = await MediaClip.CreateFromFileAsync(overlayVideoFile); // Overlay video in upper left corner, retain its native aspect ratio Rect videoOverlayPosition; var encodingProperties = overlayVideoClip.GetVideoEncodingProperties(); videoOverlayPosition.Height = mediaElement.ActualHeight / 3; videoOverlayPosition.Width = (double)encodingProperties.Width / (double)encodingProperties.Height * videoOverlayPosition.Height; videoOverlayPosition.X = 0; videoOverlayPosition.Y = 0; var videoOverlay = new MediaOverlay(overlayVideoClip); videoOverlay.Position = videoOverlayPosition; videoOverlay.Opacity = 0.75; var overlayLayer = new MediaOverlayLayer(); overlayLayer.Overlays.Add(videoOverlay); composition.OverlayLayers.Add(overlayLayer); // Render to MediaElement mediaElement.Position = TimeSpan.Zero; mediaStreamSource = composition.GeneratePreviewMediaStreamSource((int)mediaElement.ActualWidth, (int)mediaElement.ActualHeight); mediaElement.SetMediaStreamSource(mediaStreamSource); rootPage.NotifyUser("Overlays created", NotifyType.StatusMessage); }
private async Task <MediaOverlayLayer> CreateOverlay2(Interval videoInterval, Flight flight, TimeSpan period, Action <Status> onNewStatus, Rect position) { var count = videoInterval.Duration.ToTimeSpan().Divide(period); var mediaLayer = new MediaOverlayLayer(); for (var i = 0; i < count; i++) { var offset = i * period; var videoTime = videoInterval.Start.Plus(offset.ToDuration()); var flightTime = videoTime.Minus(flight.Date.ToInstant()); var status = flight.Statuses.FirstOrDefault(x => x.TimeElapsed >= flightTime.ToTimeSpan()); if (status != null) { onNewStatus(status); } var clip = await CreateMediaClip(period); var mediaOverlay = new MediaOverlay(clip) { Position = position, Delay = offset, }; mediaLayer.Overlays.Add(mediaOverlay); } return(mediaLayer); }
public void AddClip(MediaClip clip) { var aspect = clip.GetVideoEncodingProperties().PixelAspectRatio; MediaOverlay overlay = new MediaOverlay(clip, new Windows.Foundation.Rect(20, 20, 400, 400), 1); mediaOverlayLayer.Overlays.Add(overlay); AddMediaClip?.Invoke(this); }
private void AddOverlay_Click(object sender, RoutedEventArgs e) { var colorClip = MediaClip.CreateFromColor(Windows.UI.Color.FromArgb(255, 125, 0, 0), TimeSpan.FromSeconds(10)); var colorOverlay = new MediaOverlay(colorClip, new Rect(10, 10, 50, 50), 1); MediaOverlayLayer colorLayer = new MediaOverlayLayer(); colorLayer.Overlays.Add(colorOverlay); mediaComposition.OverlayLayers.Add(colorLayer); UpdateSource(); }
private async Task <MediaOverlay> CreateOverlay(Interval videoInterval, Flight flight, TimeSpan period, Action <Status> onNewStatus) { var count = videoInterval.Duration.ToTimeSpan().Divide(period); var composition = new MediaComposition(); var bmps = new List <StorageFile>(); for (var i = 0; i < count; i++) { var offset = i * period; var videoTime = videoInterval.Start.Plus(offset.ToDuration()); var flightTime = videoTime.Minus(flight.Date.ToInstant()); var status = flight.Statuses.FirstOrDefault(x => x.TimeElapsed >= flightTime.ToTimeSpan()); if (status != null) { onNewStatus(status); } var bmp = await CaptureBitmap(); bmps.Add(bmp); composition.Clips.Add(await MediaClip.CreateFromImageFileAsync(bmp, offset)); } var storageFile = await CreateFile(); await composition.RenderToFileAsync(storageFile, MediaTrimmingPreference.Fast); foreach (var bmp in bmps) { await bmp.DeleteAsync(); } var mediaClip = await MediaClip.CreateFromFileAsync(storageFile); await storageFile.DeleteAsync(); var mediaOverlay = new MediaOverlay(mediaClip) { Position = new Rect(0, 0, 200, 200), Delay = TimeSpan.Zero }; return(mediaOverlay); }
private async Task <MediaOverlayLayer> GenerateHorizonLayer(int timeInSeconds, uint height, uint width) { CanvasBitmap cb = await CanvasBitmap.LoadAsync(CanvasDevice.GetSharedDevice(), new Uri("ms-appx:///Assets/horizon3840x2160.png")); //cb.AlphaMode = CanvasAlphaMode.Straight; //img.Source = horizonFile; MediaOverlayLayer horizonOverlay = new MediaOverlayLayer(); MediaOverlay mediaOverlay = new MediaOverlay(MediaClip.CreateFromSurface(cb, new TimeSpan(0, 0, timeInSeconds))); //generowanie horyzontu mediaOverlay.Position = new Rect(0, 0, width, height); mediaOverlay.Opacity = 1; horizonOverlay.Overlays.Add(mediaOverlay); return(horizonOverlay); }
//拷贝 private void CopyButton_Tapped(object sender, TappedRoutedEventArgs e) { if (App.Model.Current != null) { //克隆 MediaClip clip = App.Model.Current.Clone(); //插入 int index = App.Model.MediaComposition.Clips.IndexOf(App.Model.Current); App.Model.MediaComposition.Clips.Insert(index, clip); //更新当前 App.Model.Current = clip; } else if (App.Model.OverlayCurrent != null) { IList <MediaOverlay> overlays = App.Model.MediaComposition.OverlayLayers[App.Model.OverlayIndex].Overlays; //克隆 MediaOverlay overlay = App.Model.OverlayCurrent.Clone(); overlay.Delay = App.Model.OverlayCurrent.Clip.EndTimeInComposition; //插入 int index = overlays.IndexOf(App.Model.OverlayCurrent); overlays.Insert(index, overlay); //更新当前 App.Model.OverlayCurrent = overlay; } else if (App.Model.AudioCurrent != null) { BackgroundAudioTrack Audio = App.Model.AudioCurrent.Clone(); App.Model.MediaComposition.BackgroundAudioTracks.Add(Audio); Audio.Delay = App.Model.AudioCurrent.Delay + App.Model.AudioCurrent.TrimmedDuration; App.Model.AudioCurrent = Audio; } App.Model.Refresh++;//画布刷新 }
// <SnippetAddOverlay> private void AddOverlay(MediaClip overlayMediaClip, double scale, double left, double top, double opacity) { Windows.Media.MediaProperties.VideoEncodingProperties encodingProperties = overlayMediaClip.GetVideoEncodingProperties(); Rect overlayPosition; overlayPosition.Width = (double)encodingProperties.Width * scale; overlayPosition.Height = (double)encodingProperties.Height * scale; overlayPosition.X = left; overlayPosition.Y = top; MediaOverlay mediaOverlay = new MediaOverlay(overlayMediaClip); mediaOverlay.Position = overlayPosition; mediaOverlay.Opacity = opacity; MediaOverlayLayer mediaOverlayLayer = new MediaOverlayLayer(); mediaOverlayLayer.Overlays.Add(mediaOverlay); composition.OverlayLayers.Add(mediaOverlayLayer); }
public async Task MergeAudioVideoWebcam(StorageFile webcamFile, StorageFile videoFile, StorageFile outputFile) { if (webcamFile == null) { if (parent != null) { parent.StartWritingOutput("Webcam File is null", 1); } return; } if (videoFile == null) { if (parent != null) { parent.StartWritingOutput("Video File is null", 1); } return; } if (outputFile == null) { if (parent != null) { parent.StartWritingOutput("Output File is null (not specified)", 1); } return; } if (!webcamFile.IsAvailable) { if (parent != null) { parent.StartWritingOutput("Webcam File is not available", 1); } return; } if (!videoFile.IsAvailable) { if (parent != null) { parent.StartWritingOutput("Video File is not available", 1); } return; } if (parent != null) { parent.StartWritingOutput("Merging temporary video and webcam files..", 1); } try { MediaClip mediaClip = await MediaClip.CreateFromFileAsync(videoFile); MediaClip webcamClip = await MediaClip.CreateFromFileAsync(webcamFile); //the BorderVideoEffects need to be in a separate Windows Component Runtime webcamClip.VideoEffectDefinitions.Add(new VideoEffectDefinition(typeof(BorderVideoEffect).FullName)); int xoffset = 20; int yoffset = 30; double overlayOpacity = 1.0; double overlayHeight = 150; Rect overlayRect; VideoEncodingProperties webcamEncodingProperties = webcamClip.GetVideoEncodingProperties(); overlayRect.Height = overlayHeight; double widthToHeightAspectRatio = ((double)webcamEncodingProperties.Width / (double)webcamEncodingProperties.Height); overlayRect.Width = widthToHeightAspectRatio * overlayHeight; overlayRect.X = xoffset; overlayRect.Y = yoffset; MediaOverlay mediaOverlay = new MediaOverlay(webcamClip); mediaOverlay.Position = overlayRect; mediaOverlay.Opacity = overlayOpacity; mediaOverlay.AudioEnabled = true; MediaOverlayLayer mediaOverlayLayer = new MediaOverlayLayer(); mediaOverlayLayer.Overlays.Add(mediaOverlay); MediaComposition mediaComposition = new MediaComposition(); mediaComposition.Clips.Add(mediaClip); mediaComposition.OverlayLayers.Add(mediaOverlayLayer); if (outputFile != null) { var mergeOperation = mediaComposition.RenderToFileAsync(outputFile, MediaTrimmingPreference.Precise); mergeOperation.Progress += mergeWebcamProgress; mergeOperation.Completed += mergeWebcamCompleted; } } catch (Exception e) { if (parent != null) { parent.StartWritingOutput("Merge Error :" + e.Message, 1); } } }
public async Task <MediaStreamSource> GenerateHeatmap(bool scaleFovFlag, int scaleInPercentage, bool forceFov, int forcedFov, bool horizonFlag, SessionCollection sessions, Rect overlayPosition, Windows.UI.Color colorPickerColor, double heatmapOpacity, double startTime, double stopTime, MediaClip video) { CheckHistoryErrors(sessions); List <Heatmap.Coord> inputList = await Task.Factory.StartNew(() => TrimStaticHeatmap(sessions, startTime, stopTime, video) ); MediaOverlayLayer mediaOverlayLayer = new MediaOverlayLayer(); WriteableBitmap wb = await GenerateHeatmap(inputList, forceFov, forcedFov, scaleFovFlag, scaleInPercentage); CanvasDevice device = CanvasDevice.GetSharedDevice(); SoftwareBitmap swb = SoftwareBitmap.CreateCopyFromBuffer(wb.PixelBuffer, BitmapPixelFormat.Bgra8, wb.PixelWidth, wb.PixelHeight); swb = SoftwareBitmap.Convert(swb, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore); CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(device, swb); var clip = MediaClip.CreateFromSurface(canvasBitmap, new TimeSpan(0, 0, 0, 0, 1)); MediaOverlay mediaOverlay = new MediaOverlay(clip) { Position = overlayPosition, Opacity = heatmapOpacity }; mediaOverlayLayer.Overlays.Add(mediaOverlay); if (horizonFlag) { CanvasBitmap cb = await CanvasBitmap.LoadAsync(CanvasDevice.GetSharedDevice(), new Uri("ms-appx:///Assets/horizon3840x2160.png")); MediaOverlay horizonOverlay = new MediaOverlay(MediaClip.CreateFromSurface(cb, new TimeSpan(0, 0, 0, 0, 1))) { Position = overlayPosition, Opacity = 1 }; mediaOverlayLayer.Overlays.Add(horizonOverlay); } MediaComposition mediaComposition = new MediaComposition(); mediaComposition.Clips.Add(MediaClip.CreateFromColor(colorPickerColor, new TimeSpan(0, 0, 0, 0, 1))); mediaComposition.OverlayLayers.Add(mediaOverlayLayer); return(mediaComposition.GeneratePreviewMediaStreamSource ( (int)overlayPosition.Width, (int)overlayPosition.Height )); }
private Task CreateExportTask(CancellationToken cancellationToken) { return(new Task(() => { var provider = this.ExportProvider; var mediaEncodingProfile = MediaEncodingProfile.CreateMp4(this.ExportVideoEncodingQuality); if (provider?.ExportPartConfigs == null || this.DestinationFolder == null || provider.ExportPartConfigs.Count < 1 || string.IsNullOrEmpty(this.FileName) || Math.Abs(provider.ExportSize.Width) < 1 || Math.Abs(provider.ExportSize.Height) < 1 || mediaEncodingProfile?.Video == null) { UpdateExportStatus(false); return; } var exportSize = provider.ExportSize; mediaEncodingProfile.Video.Width = (uint)exportSize.Width; mediaEncodingProfile.Video.Height = (uint)exportSize.Height; mediaEncodingProfile.Video.FrameRate.Numerator = this.ExportFrameRate; var cacheFolder = GetCacheFolder().GetAwaiter().GetResult(); var device = CanvasDevice.GetSharedDevice(); var mediafileList = new List <StorageFile>(); var defaultBackgroud = new CanvasRenderTarget(device, (float)exportSize.Width, (float)exportSize.Height, 96f); using (var session = defaultBackgroud.CreateDrawingSession()) { session.Clear(Colors.White); } var scale = exportSize.Width / provider.ExportArea.Width; var transform = Matrix3x2.CreateScale((float)scale); var offsetPoint = Vector2.Transform(new Point(-provider.ExportArea.X, -provider.ExportArea.Y).ToVector2(), transform); transform.Translation = offsetPoint; var framePosition = new Rect(new Point(), exportSize); var timeGap = TimeSpan.FromSeconds(1) / provider.FrameRate; foreach (var videoPartConfig in provider.ExportPartConfigs) { var composition = new MediaComposition(); var layerTmp = new MediaOverlayLayer(); var tmpFrameImgs = new List <CanvasBitmap>(); if (videoPartConfig.BackgroundVideoClips?.Count > 0) { if (videoPartConfig.Delay.TotalSeconds > 0) { var blankClip = MediaClip.CreateFromColor(Colors.White, videoPartConfig.Delay); composition.Clips.Add(blankClip); } foreach (var videoClip in videoPartConfig.BackgroundVideoClips) { composition.Clips.Add(videoClip); } if (composition.Duration < videoPartConfig.Duration) { var blankClip = MediaClip.CreateFromColor(Colors.White, videoPartConfig.Duration - composition.Duration); composition.Clips.Add(blankClip); } } else { composition.Clips.Add(MediaClip.CreateFromSurface(defaultBackgroud, videoPartConfig.Duration)); } if (videoPartConfig.BackgroundAudioTracks?.Count > 0) { foreach (var track in videoPartConfig.BackgroundAudioTracks) { track.Delay -= videoPartConfig.Start; composition.BackgroundAudioTracks.Add(track); } } for (var currentPosition = videoPartConfig.Start; currentPosition < videoPartConfig.Start + videoPartConfig.Duration; currentPosition += timeGap) { if (Canceled) { return; } var progress = (int)(currentPosition / provider.Duration * 100 * 0.5); UpdateProgress(progress); var frame = new CanvasRenderTarget(device, (float)exportSize.Width, (float)exportSize.Height, 96f); using (var session = frame.CreateDrawingSession()) { session.Clear(Colors.Transparent); session.Transform = transform; provider.DrawFrame(session, currentPosition); } tmpFrameImgs.Add(frame); var clip = MediaClip.CreateFromSurface(frame, timeGap); var tmpLayer = new MediaOverlay(clip) { Position = framePosition, Opacity = 1f, Delay = currentPosition - videoPartConfig.Start }; layerTmp.Overlays.Add(tmpLayer); } composition.OverlayLayers.Add(layerTmp); var mediaPartFile = cacheFolder.CreateFileAsync( $"part_{mediafileList.Count}.mp4", CreationCollisionOption.ReplaceExisting).GetAwaiter() .GetResult(); composition.RenderToFileAsync(mediaPartFile, MediaTrimmingPreference.Fast, mediaEncodingProfile).GetAwaiter().GetResult(); mediafileList.Add(mediaPartFile); foreach (var item in tmpFrameImgs) { item.Dispose(); } tmpFrameImgs.Clear(); } defaultBackgroud?.Dispose(); var mediaComposition = new MediaComposition(); #region connect video foreach (var mediaPartFile in mediafileList) { if (Canceled) { return; } var mediaPartClip = MediaClip.CreateFromFileAsync(mediaPartFile).GetAwaiter().GetResult(); mediaComposition.Clips.Add(mediaPartClip); } #endregion #region add global BackgroundAudioTrack if (provider.GlobalBackgroundAudioTracks != null) { foreach (var bgm in provider.GlobalBackgroundAudioTracks) { mediaComposition.BackgroundAudioTracks.Add(bgm); } } #endregion #region add watermark var watermarkLayer = provider.CreateWatermarkLayer(); if (watermarkLayer != null) { mediaComposition.OverlayLayers.Add(watermarkLayer); } #endregion var exportFile = this.DestinationFolder.CreateFileAsync($"{this.FileName}.mp4", CreationCollisionOption.ReplaceExisting) .GetAwaiter().GetResult(); if (Canceled) { return; } var saveOperation = mediaComposition.RenderToFileAsync(exportFile, MediaTrimmingPreference.Fast, mediaEncodingProfile); saveOperation.Progress = (info, progress) => { UpdateProgress((int)(50 + progress * 0.5)); if (Canceled) { saveOperation.Cancel(); } }; saveOperation.Completed = (info, status) => { if (!Canceled) { var results = info.GetResults(); if (results != TranscodeFailureReason.None || status != AsyncStatus.Completed) { UpdateExportStatus(false); } else { UpdateExportStatus(true); } } ClearCacheAsync(); }; }, cancellationToken)); }
//裁剪 private void TrimButton_Tapped(object sender, TappedRoutedEventArgs e) { TimeSpan Position = App.Model.MediaPlayer.Position; if (App.Model.Current != null) { //寻找当前媒体剪辑 int index = App.Model.MediaComposition.Clips.IndexOf(App.Model.Current); if (Position > App.Model.Current.StartTimeInComposition && Position < App.Model.Current.EndTimeInComposition) { //克隆并剪切 MediaClip clipA = App.Model.Current.Clone(); clipA.TrimTimeFromEnd = (App.Model.Current.EndTimeInComposition + App.Model.Current.TrimTimeFromEnd) - Position; MediaClip clipB = App.Model.Current.Clone(); clipB.TrimTimeFromStart = Position - (App.Model.Current.StartTimeInComposition - App.Model.Current.TrimTimeFromStart); //移除并插入 App.Model.MediaComposition.Clips.Remove(App.Model.Current); App.Model.MediaComposition.Clips.Insert(index, clipB); App.Model.MediaComposition.Clips.Insert(index, clipA); App.Model.Current = clipB; } } else if (App.Model.OverlayCurrent != null) { IList <MediaOverlay> overlays = App.Model.MediaComposition.OverlayLayers[App.Model.OverlayIndex].Overlays; if (Position > App.Model.OverlayCurrent.Clip.StartTimeInComposition && Position < App.Model.OverlayCurrent.Clip.EndTimeInComposition) { //克隆并剪切 MediaOverlay overlayA = App.Model.OverlayCurrent.Clone(); overlayA.Clip.TrimTimeFromEnd = (App.Model.OverlayCurrent.Clip.EndTimeInComposition + App.Model.OverlayCurrent.Clip.TrimTimeFromEnd) - Position; MediaOverlay overlayB = App.Model.OverlayCurrent.Clone(); overlayB.Clip.TrimTimeFromStart = Position - (App.Model.OverlayCurrent.Clip.StartTimeInComposition - App.Model.OverlayCurrent.Clip.TrimTimeFromStart); overlayB.Delay = Position; //移除并插入 overlays.Remove(App.Model.OverlayCurrent); overlays.Add(overlayA); overlays.Add(overlayB); App.Model.OverlayCurrent = overlayB; } } else if (App.Model.AudioCurrent != null) { if (Position > App.Model.AudioCurrent.Delay && Position < App.Model.AudioCurrent.Delay + App.Model.AudioCurrent.TrimmedDuration) { //克隆并剪切 BackgroundAudioTrack audioA = App.Model.AudioCurrent.Clone(); audioA.TrimTimeFromEnd = (App.Model.AudioCurrent.Delay + App.Model.AudioCurrent.TrimmedDuration + App.Model.AudioCurrent.TrimTimeFromEnd) - Position; BackgroundAudioTrack audioB = App.Model.AudioCurrent.Clone(); audioB.TrimTimeFromStart = Position - (App.Model.AudioCurrent.Delay - App.Model.AudioCurrent.TrimTimeFromStart); audioB.Delay = Position; //移除并插入 App.Model.MediaComposition.BackgroundAudioTracks.Remove(App.Model.AudioCurrent); App.Model.MediaComposition.BackgroundAudioTracks.Add(audioA); App.Model.MediaComposition.BackgroundAudioTracks.Add(audioB); App.Model.AudioCurrent = audioB; } } }
private void CanvasControl_Drop(object sender, DragEventArgs e) { DragOperationDeferral def = e.GetDeferral(); def.Complete(); if (App.Model.Drop.Clip != null) { Point p = e.GetPosition(CanvasControl); //Main:主剪辑 if (p.Y < App.Setting.Space + App.Setting.RulerSpace) { MediaClip clip = App.Model.Drop.Clip.Clone(); TimeSpan postion = App.Model.ScreenToCanvas((float)p.X); //当前时间 TimeSpan postiondouble = postion + postion; //双倍当前时间(为了与以后的start+end做比较计算) if (App.Model.MediaComposition.Clips.Count == 0) //轨道是空的 { App.Model.MediaComposition.Clips.Add(clip); } else if (App.Model.MediaComposition.Clips.Count == 1)//轨道上只有一个 { var First = App.Model.MediaComposition.Clips.First(); if (postiondouble < First.StartTimeInComposition + First.EndTimeInComposition) { App.Model.MediaComposition.Clips.Insert(0, clip); } else { App.Model.MediaComposition.Clips.Insert(1, clip); } } else//轨道上有多个 { //判断是否超出第一个剪辑的结束时间 MediaClip First = App.Model.MediaComposition.Clips.FirstOrDefault(); if (postiondouble < First.StartTimeInComposition + First.EndTimeInComposition) { App.Model.MediaComposition.Clips.Insert(0, clip); } //循环,寻找中间落脚点在哪里 TimeSpan OldStartAndEnd = TimeSpan.Zero; for (int i = 1; i < App.Model.MediaComposition.Clips.Count; i++) { MediaClip Current = App.Model.MediaComposition.Clips[i]; //是否处于前一个媒体剪辑与后一个媒体剪辑的中点之间 if (postiondouble > OldStartAndEnd && postiondouble < Current.StartTimeInComposition + Current.EndTimeInComposition) { App.Model.MediaComposition.Clips.Insert(i, clip); } OldStartAndEnd = Current.StartTimeInComposition + Current.EndTimeInComposition;//新旧交替 } //判断是否超出最后一个剪辑的结束时间 MediaClip Last = App.Model.MediaComposition.Clips.LastOrDefault(); if (postiondouble > Last.StartTimeInComposition + Last.EndTimeInComposition) { App.Model.MediaComposition.Clips.Insert(App.Model.MediaComposition.Clips.Count, clip); } } //设此媒体剪辑为当前媒体剪辑当前 App.Model.Current = clip; App.Model.OverlayCurrent = null; } else { //OverlayMove:覆盖移动 for (int i = 0; i < App.Model.MediaComposition.OverlayLayers.Count; i++) { float top = App.Setting.RulerSpace + App.Setting.Space + i * App.Setting.OverlaySpace; //顶部 float height = App.Setting.OverlaySpace; //高度 float bottom = top + height; //底部 if (p.Y > top && p.Y < bottom) { App.Model.OverlayIndex = i; MediaClip clip = App.Model.Drop.Clip.Clone(); MediaOverlay Overlay = new MediaOverlay(clip); Overlay.Position = new Rect(100, 0, 666, 222); App.Model.MediaComposition.OverlayLayers[i].Overlays.Add(Overlay); Overlay.Delay = App.Model.ScreenToCanvas((float)p.X); App.Model.Current = null; App.Model.OverlayCurrent = Overlay; App.Model.AudioCurrent = null; } } } App.Model.MediaPlayer.Source = MediaSource.CreateFromMediaStreamSource ( App.Model.MediaComposition.GeneratePreviewMediaStreamSource(0, 0) ); this.MediaPlayerElement.SetMediaPlayer(App.Model.MediaPlayer); App.Model.Refresh++;//画布刷新 App.Model.Drop = null; } }
private async Task ChatPhotoAsync(UpdateFileGenerationStart update, string[] args) { try { var conversion = JsonConvert.DeserializeObject <ChatPhotoConversion>(args[2]); var sticker = await _protoService.SendAsync(new GetFile(conversion.StickerFileId)) as Telegram.Td.Api.File; if (sticker == null || !sticker.Local.IsFileExisting()) { _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, "FILE_GENERATE_LOCATION_INVALID No sticker found"))); return; } Background background = null; var backgroundLink = await _protoService.SendAsync(new GetInternalLinkType(conversion.BackgroundUrl ?? string.Empty)) as InternalLinkTypeBackground; if (backgroundLink != null) { background = await _protoService.SendAsync(new SearchBackground(backgroundLink.BackgroundName)) as Background; } else { var freeform = new[] { 0xDBDDBB, 0x6BA587, 0xD5D88D, 0x88B884 }; background = new Background(0, true, false, string.Empty, new Document(string.Empty, "application/x-tgwallpattern", null, null, TdExtensions.GetLocalFile("Assets\\Background.tgv", "Background")), new BackgroundTypePattern(new BackgroundFillFreeformGradient(freeform), 50, false, false)); } if (background == null || (background.Document != null && !background.Document.DocumentValue.Local.IsFileExisting())) { _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, "FILE_GENERATE_LOCATION_INVALID No background found"))); return; } var device = CanvasDevice.GetSharedDevice(); var bitmaps = new List <CanvasBitmap>(); var sfondo = new CanvasRenderTarget(device, 640, 640, 96, DirectXPixelFormat.B8G8R8A8UIntNormalized, CanvasAlphaMode.Premultiplied); using (var session = sfondo.CreateDrawingSession()) { if (background.Type is BackgroundTypePattern pattern) { if (pattern.Fill is BackgroundFillFreeformGradient freeform) { var colors = freeform.GetColors(); var positions = new Vector2[] { new Vector2(0.80f, 0.10f), new Vector2(0.35f, 0.25f), new Vector2(0.20f, 0.90f), new Vector2(0.65f, 0.75f), }; using (var gradient = CanvasBitmap.CreateFromBytes(device, ChatBackgroundFreeform.GenerateGradientData(50, 50, colors, positions), 50, 50, DirectXPixelFormat.B8G8R8A8UIntNormalized)) using (var cache = await PlaceholderHelper.GetPatternBitmapAsync(device, null, background.Document.DocumentValue)) { using (var scale = new ScaleEffect { Source = gradient, BorderMode = EffectBorderMode.Hard, Scale = new Vector2(640f / 50f, 640f / 50f) }) using (var colorize = new TintEffect { Source = cache, Color = Color.FromArgb(0x76, 00, 00, 00) }) using (var tile = new BorderEffect { Source = colorize, ExtendX = CanvasEdgeBehavior.Wrap, ExtendY = CanvasEdgeBehavior.Wrap }) using (var effect = new BlendEffect { Foreground = tile, Background = scale, Mode = BlendEffectMode.Overlay }) { session.DrawImage(effect, new Rect(0, 0, 640, 640), new Rect(0, 0, 640, 640)); } } } } } bitmaps.Add(sfondo); var width = (int)(512d * conversion.Scale); var height = (int)(512d * conversion.Scale); var animation = await Task.Run(() => LottieAnimation.LoadFromFile(sticker.Local.Path, new Windows.Graphics.SizeInt32 { Width = width, Height = height }, false, null)); if (animation == null) { _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, "FILE_GENERATE_LOCATION_INVALID Can't load Lottie animation"))); return; } var composition = new MediaComposition(); var layer = new MediaOverlayLayer(); var buffer = ArrayPool <byte> .Shared.Rent(width *height * 4); var framesPerUpdate = animation.FrameRate < 60 ? 1 : 2; var duration = TimeSpan.Zero; for (int i = 0; i < animation.TotalFrame; i += framesPerUpdate) { var bitmap = CanvasBitmap.CreateFromBytes(device, buffer, width, height, DirectXPixelFormat.B8G8R8A8UIntNormalized); animation.RenderSync(bitmap, i); var clip = MediaClip.CreateFromSurface(bitmap, TimeSpan.FromMilliseconds(1000d / 30d)); var overlay = new MediaOverlay(clip, new Rect(320 - (width / 2d), 320 - (height / 2d), width, height), 1); overlay.Delay = duration; layer.Overlays.Add(overlay); duration += clip.OriginalDuration; bitmaps.Add(bitmap); } composition.OverlayLayers.Add(layer); composition.Clips.Add(MediaClip.CreateFromSurface(sfondo, duration)); var temp = await _protoService.GetFileAsync(update.DestinationPath); var profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto); profile.Audio = null; profile.Video.Bitrate = 1800000; profile.Video.Width = 640; profile.Video.Height = 640; profile.Video.FrameRate.Numerator = 30; profile.Video.FrameRate.Denominator = 1; var progress = composition.RenderToFileAsync(temp, MediaTrimmingPreference.Precise, profile); progress.Progress = (result, delta) => { _protoService.Send(new SetFileGenerationProgress(update.GenerationId, 100, (int)delta)); }; var result = await progress; if (result == TranscodeFailureReason.None) { _protoService.Send(new FinishFileGeneration(update.GenerationId, null)); } else { _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, result.ToString()))); } ArrayPool <byte> .Shared.Return(buffer); foreach (var bitmap in bitmaps) { bitmap.Dispose(); } } catch (Exception ex) { _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, "FILE_GENERATE_LOCATION_INVALID " + ex.ToString()))); } }
void T() { MediaOverlay over = new MediaOverlay(null); }