private Tuple <AvsNode, int> GetChainNodeAndNewIndex(int index, List <StreamChunk> initialChunks, int shift, int fps) { var finalChunks = new List <StreamChunk>(); finalChunks.Add(initialChunks[index]); for (var i = index; i < initialChunks.Count - 1; i++) { var currentChunk = initialChunks[i]; var nextChunk = initialChunks[i + 1]; if (initialChunks[i].IsActive && IsDifferentMode(currentChunk.Mode, nextChunk.Mode)) { finalChunks.Add(nextChunk); } else if (finalChunks.Count > 1) { AvsConcatList videoChunk = new AvsConcatList(); videoChunk.Items = new List <AvsNode>() { }; foreach (var e in finalChunks) { videoChunk.Items.Add(AvsNode.NormalizedNode(e, fps, currentChunk.Mode == Mode.Face, shift)); } var startTime = finalChunks[0].StartTime; var startLength = finalChunks[0].Length; var length = startTime + finalChunks.Select(x => x.Length).Sum(); var audioChunk = new StreamChunk(startTime, length, Mode.Face, currentChunk.Mode == Mode.Face); AvsNode audioAvsChunk = AvsNode.NormalizedNode(audioChunk, fps, currentChunk.Mode == Mode.Face, shift); AvsMix mix = new AvsMix(); mix.First = videoChunk; mix.Second = audioAvsChunk; return(new Tuple <AvsNode, int>(mix, i)); } else { return(null); } } return(null); }
private AvsNode MakeEpisode(EditorModel model, List <FileChunk> fileChunks) { var avsChunks = new AvsConcatList { Items = new List <AvsNode>() }; avsChunks.Items.Add(AvsNode.NormalizedNode(model.Locations.Make(model.ChunkFolder, fileChunks[0].ChunkFilename), fileChunks[0].Mode == Mode.Face)); //making cross-fades for (int i = 1; i < fileChunks.Count; i++) { var currentChunk = fileChunks[i]; var prevChunk = fileChunks[i - 1]; AvsNode currentAvsChunk = AvsNode.NormalizedNode(model.Locations.Make(model.ChunkFolder, currentChunk.ChunkFilename), currentChunk.Mode == Mode.Face); AvsNode prevAvsChunk = avsChunks.Items[avsChunks.Items.Count - 1]; if (prevChunk.Mode == Mode.Face && currentChunk.Mode == Mode.Face) { avsChunks.Items[avsChunks.Items.Count - 1] = new AvsCrossFade { FadeFrom = prevAvsChunk, FadeTo = currentAvsChunk } } ; else { avsChunks.Items.Add(currentAvsChunk); } } // intro with fadein and fadeout var intro = new AvsIntro { VideoReference = model.Locations.Make(model.ChunkFolder, fileChunks[0].ChunkFilename), ImageFile = model.Locations.IntroImage }; var normalizedIntro = AvsNode.NormalizedNode(intro); var fadedIntro = new AvsFadeIn { Payload = new AvsFadeOut { Payload = normalizedIntro } }; avsChunks.Items.Insert(0, fadedIntro); // fadeout last item avsChunks.Items[avsChunks.Items.Count - 1] = new AvsFadeOut { Payload = avsChunks.Items[avsChunks.Items.Count - 1] }; // autolevel // ??? // watermark return(new AvsWatermark { Payload = avsChunks, ImageFile = model.Locations.WatermarkImage }); /* * add intro * make crossfades * add fadein/fadeout * add autolevel? * add watermark */ }
private AvsNode MakeEpisode(EditorModel model, EpisodesChunks episode) { var chunks = episode.chunks; var avsChunks = new AvsConcatList { Items = new List <AvsNode>() }; var fps = 25; var shift = model.Montage.SynchronizationShift; var currentChunk = chunks[0]; //making cross-fades and merging for (int i = 0; i < chunks.Count; i++) { if (chunks[i].IsNotActive) { continue; } var prevChunk = i >= 1 ? currentChunk : null; currentChunk = chunks[i]; AvsNode currentAvsChunk = AvsNode.NormalizedNode(currentChunk, fps, currentChunk.Mode == Mode.Face, shift); AvsNode prevAvsChunk = avsChunks.Items.Count >= 1 ? avsChunks.Items[avsChunks.Items.Count - 1] : AvsNode.NormalizedNode(chunks[0], fps, false, shift); //Оптимизация face-desktop et cetera if (UseChainProcessing) { var chain = GetChainNodeAndNewIndex(i, chunks, shift, fps); if (chain != null) { currentAvsChunk = chain.Item1; i = chain.Item2; } } if (prevChunk != null && prevChunk.Mode == Mode.Face && currentChunk.Mode == Mode.Face && CrossFadesEnabled) { avsChunks.Items[avsChunks.Items.Count - 1] = new AvsCrossFade { FadeFrom = prevAvsChunk, FadeTo = currentAvsChunk } } ; else if (currentChunk.IsActive) { avsChunks.Items.Add(currentAvsChunk); } currentChunk = chunks[i]; } // intro with fadein and fadeout //var intro = new AvsIntro //{ // VideoReference = model.Locations.Make(model.ChunkFolder, fileChunks[0].ChunkFilename), // ImageFile = model.Locations.IntroImage //}; //var normalizedIntro = AvsNode.NormalizedNode(intro); //var fadedIntro = new AvsFadeIn {Payload = new AvsFadeOut {Payload = normalizedIntro}}; //avsChunks.Items.Insert(0, fadedIntro); // fadeout last item avsChunks.Items[avsChunks.Items.Count - 1] = new AvsFadeOut { Payload = avsChunks.Items[avsChunks.Items.Count - 1] }; //AvsNode resultedAvs = avsChunks; //if (!string.IsNullOrEmpty(File.ReadAllText(model.Locations.GetSrtFile(episode.episodeNumber).FullName))) //{ // resultedAvs = new AvsSubtitle { SrtPath = model.Locations.GetSrtFile(episode.episodeNumber).FullName, Payload = avsChunks }; //} // autolevel // ??? return(avsChunks); // watermark //return new AvsWatermark //{ // Payload = avsChunks, // ImageFile = model.Locations.WatermarkImage //}; /* * add intro * make crossfades * add fadein/fadeout * add autolevel? * add watermark */ }
public override void Work() { var src = pmodel.SourceInfo; List <AvsNode> chunks = new List <AvsNode>(); var tracks = pmodel.MediaTracks.OrderBy(x => x.LeftShiftInSeconds).ToList(); oldName = pmodel.SourceInfo.FullName; newName = Path.Combine(pmodel.SourceInfo.Directory.FullName, Guid.NewGuid().ToString() + ".avi"); File.Move(oldName, newName); double previous = 0; int index = 0; string mode = "main"; while (Math.Abs(previous - pmodel.Duration) >= 0.5 && tracks.Count != 0) { var avs = new AvsPatchChunk(); if (mode == "main") { var endTime = index >= tracks.Count ? pmodel.Duration : tracks[index].StartSecond + tracks[index].LeftShiftInSeconds; avs.Load(newName, previous, endTime); previous = endTime; chunks.Add(avs); mode = "patch"; continue; } var name = tracks[index].IsTutoPatch ? tracks[index].Path.LocalPath : Path.Combine(Model.Locations.TemporalDirectory.FullName, tracks[index].FullName.Name); avs.Load(name, tracks[index].StartSecond, tracks[index].EndSecond); chunks.Add(avs); previous = tracks[index].EndSecond + tracks[index].LeftShiftInSeconds; index++; mode = "main"; } if (tracks.Count == 0) { var s = new AvsPatchChunk(); s.Load(newName, 0, pmodel.Duration); chunks.Add(s); } var final = new AvsConcatList(); final.Items = chunks; var avsContext = new AvsContext(); AvsNode payload = final; if (pmodel.Subtitles.Count > 0) { var currentSub = new AvsSub(); foreach (var sub in pmodel.Subtitles) { currentSub = new AvsSub(); currentSub.Payload = payload; currentSub.X = (int)(sub.Pos.X * pmodel.Width / pmodel.ActualWidth); currentSub.Y = (int)(sub.Pos.Y * pmodel.Height / pmodel.ActualHeight + sub.HeightShift); currentSub.Start = sub.LeftShiftInSeconds; currentSub.End = sub.LeftShiftInSeconds + sub.EndSecond - sub.StartSecond; currentSub.Content = sub.Content; currentSub.FontSize = (sub.FontSize * pmodel.FontCoefficent).ToString(); currentSub.Stroke = sub.Stroke; currentSub.Foreground = sub.Foreground; payload = currentSub; } currentSub.SerializeToContext(avsContext); } else { final.SerializeToContext(avsContext); } var args = @"-i ""{0}"" -q:v 0 -vf ""scale=1280:720, fps=25"" -q:v 0 -acodec libmp3lame -ar 44100 -ab 32k ""{1}"" -y"; var avsScript = string.Format(@"import(""{0}"")", Model.Locations.AvsLibrary.FullName) + "\r\n" + avsContext.GetContent() + "var_0"; File.WriteAllText(newName + "test.avs", avsScript, Encoding.GetEncoding("Windows-1251")); //Патчер в аутпут все делает var scriptFile = newName + "test.avs"; var path = Model.Locations.GetFinalOutputFile(pmodel.EpisodeNumber).FullName; args = string.Format(args, scriptFile, path); RunProcess(args, Model.Videotheque.Locations.FFmpegExecutable.FullName); File.Delete(scriptFile); OnTaskFinished(); File.Move(newName, oldName); }