public static RenderableProject GetVideoClipsForRendering(this VidkaProj proj) { var arrClips = proj.ClipsVideo.ToArray(); var fileList1 = arrClips .DistinctHaving(x => x.FileName) .Select(x => new RenderableMediaFile { FileName = x.FileName, VarName = x.FileName.FilenameToVarName(), Type = GetRenderableVideoFileType(x), }); // custom audios... var fileList2 = arrClips .Where(x => x.HasCustomAudio) .DistinctHaving(x => x.CustomAudioFilename) .Select(x => new RenderableMediaFile { FileName = x.CustomAudioFilename, VarName = x.CustomAudioFilename.FilenameToVarName(), Type = RenderableMediaFileType.AudioSource, }); var fileList = fileList1 .Union(fileList2) .DistinctHaving(x => x.FileName) .ToList(); var arrClips2 = arrClips.Select((x, i) => new VideoClipRenderable { VarName = x.FileName.FilenameToVarName() + "_" + i, VideoFile = fileList.FirstOrDefault(y => y.FileName == x.FileName), FrameStart = x.FrameStart, FrameEnd = x.FrameEnd, EasingLeft = x.EasingLeft, EasingRight = x.EasingRight, IsMuted = x.IsMuted, PostOp = x.PostOp, HasCustomAudio = x.HasCustomAudio, CustomAudioFile = fileList.FirstOrDefault(y => y.FileName == x.CustomAudioFilename), CustomAudioOffset = x.CustomAudioOffset, ClipType = GetRenderableTypeOfClip(x), }).ToArray(); long maxLengthOfImageClip = 0; var imageClips = arrClips.Where(x => x is VidkaClipImage || x is VidkaClipTextSimple); if (imageClips.Any()) maxLengthOfImageClip = imageClips.Select(x => x.LengthFrameCalc).Max(); // .... set up the easings and their audio mixes long curFrameEnd = 0; for (int i = 0; i < arrClips2.Length; i++) { curFrameEnd += arrClips2[i].LengthFrameCalc; if (arrClips2[i].EasingLeft == 0 && arrClips2[i].EasingRight == 0) continue; if (arrClips2[i].EasingLeft > 0) { var curFrame = curFrameEnd - arrClips2[i].LengthFrameCalc; long easeEndAbs = curFrame - arrClips2[i].EasingLeft; // ... begin counting from clip's beginning and end (right) of left ease long easerFrame = arrClips2[i].EasingLeft; var index = i; // ... walk backward until easing is used up while (curFrame > easeEndAbs && index > 0) { index--; long curClipLen = arrClips2[index].LengthFrameCalcNoEasing; long easerFrame1 = easerFrame - curClipLen; long easerFrame2 = easerFrame; long easerOffset = 0; // ... when offset is needed, when curClipLen (clip being audio-ed) is longer than the easing. Easing audio will begin at the right side of this clip using the offset if (easerFrame1 < 0) { easerOffset = -easerFrame1; easerFrame1 = 0; } arrClips2[index].MixesAudioFromVideo.Add(new VideoEasingAudioToMix { ClipVarName = arrClips2[i].VarName, FrameStart = easerFrame1, FrameEnd = easerFrame2, FrameOffset = easerOffset, }); curFrame -= curClipLen; easerFrame -= curClipLen; } } if (arrClips2[i].EasingRight > 0) { var curFrame = curFrameEnd; long easeEndAbs = curFrame + arrClips2[i].EasingRight; // ... begin counting from clip's end and beginning (left) of right ease long easerFrame = arrClips2[i].LengthFrameCalc - arrClips2[i].EasingRight; var index = i; // ... walk forward until easing is used up while (curFrame < easeEndAbs && index < arrClips2.Length - 1) { index++; long curClipLen = arrClips2[index].LengthFrameCalcNoEasing; long easerFrame1 = easerFrame; long easerFrame2 = easerFrame + curClipLen; // ... when curClipLen (the clip being audio-ed) exceeds the overflow. Overflow is small and overflows in just the first part of the clip if (easerFrame2 > arrClips2[i].FrameEnd) { easerFrame2 = arrClips2[i].FrameEnd; } arrClips2[index].MixesAudioFromVideo.Add(new VideoEasingAudioToMix { ClipVarName = arrClips2[i].VarName, FrameStart = easerFrame1, FrameEnd = easerFrame2, FrameOffset = 0, }); curFrame += curClipLen; easerFrame += curClipLen; } } } var statVideos = arrClips2; //... this is important to reduce AVS overhead var firstStatCandidate = arrClips.FirstOrDefault(x => x.IsPixelTypeStandard); if (firstStatCandidate != null) statVideos = new[] { new VideoClipRenderable { VideoFile = fileList.FirstOrDefault(f => f.FileName == firstStatCandidate.FileName) }}; //... this is more important when project was cropped, b/c for cropped projects the clip marked // as IsPixelTypeStandard can easily be outside if (proj.PixelTypeStandardClip != null) { var videoFileForThisOne = fileList.FirstOrDefault(f => f.FileName == proj.PixelTypeStandardClip.FileName); if (videoFileForThisOne == null) fileList.Add(videoFileForThisOne = new RenderableMediaFile { FileName = proj.PixelTypeStandardClip.FileName, VarName = proj.PixelTypeStandardClip.FileName.FilenameToVarName(), Type = GetRenderableVideoFileType(proj.PixelTypeStandardClip), }); statVideos = new[] { new VideoClipRenderable { VideoFile = videoFileForThisOne }}; } // ... make file var names all unique foreach (var fileFile in fileList) { var nonUniques = fileList.Where(x => x != fileFile && x.VarName == fileFile.VarName); foreach (var nonUnique in nonUniques) nonUnique.VarName += "__" + VidkaIO.MakeGuidWord(); } return new RenderableProject { Files = fileList, Clips = arrClips2, MaxLengthOfImageClip = maxLengthOfImageClip, StatVideos = statVideos, AudioClips = proj.ClipsAudio.Select(x => new AudioClipRenderable { FileName = x.FileName, FrameStart = x.FrameStart, FrameEnd = x.FrameEnd, FrameOffset = x.FrameOffset, PostOp = x.PostOp, }), }; }
public static RenderableProject GetVideoClipsForRendering(this VidkaProj proj) { var arrClips = proj.ClipsVideo.ToArray(); var fileList1 = arrClips .DistinctHaving(x => x.FileName) .Select(x => new RenderableMediaFile { FileName = x.FileName, VarName = x.FileName.FilenameToVarName(), Type = GetRenderableVideoFileType(x), }); // custom audios... var fileList2 = arrClips .Where(x => x.HasCustomAudio) .DistinctHaving(x => x.CustomAudioFilename) .Select(x => new RenderableMediaFile { FileName = x.CustomAudioFilename, VarName = x.CustomAudioFilename.FilenameToVarName(), Type = RenderableMediaFileType.AudioSource, }); var fileList = fileList1 .Union(fileList2) .DistinctHaving(x => x.FileName) .ToList(); var arrClips2 = arrClips.Select((x, i) => new VideoClipRenderable { VarName = x.FileName.FilenameToVarName() + "_" + i, VideoFile = fileList.FirstOrDefault(y => y.FileName == x.FileName), FrameStart = x.FrameStart, FrameEnd = x.FrameEnd, EasingLeft = x.EasingLeft, EasingRight = x.EasingRight, IsMuted = x.IsMuted, PostOp = x.PostOp, HasCustomAudio = x.HasCustomAudio, CustomAudioFile = fileList.FirstOrDefault(y => y.FileName == x.CustomAudioFilename), CustomAudioOffset = x.CustomAudioOffset, ClipType = GetRenderableTypeOfClip(x), }).ToArray(); long maxLengthOfImageClip = 0; var imageClips = arrClips.Where(x => x is VidkaClipImage || x is VidkaClipTextSimple); if (imageClips.Any()) { maxLengthOfImageClip = imageClips.Select(x => x.LengthFrameCalc).Max(); } // .... set up the easings and their audio mixes long curFrameEnd = 0; for (int i = 0; i < arrClips2.Length; i++) { curFrameEnd += arrClips2[i].LengthFrameCalc; if (arrClips2[i].EasingLeft == 0 && arrClips2[i].EasingRight == 0) { continue; } if (arrClips2[i].EasingLeft > 0) { var curFrame = curFrameEnd - arrClips2[i].LengthFrameCalc; long easeEndAbs = curFrame - arrClips2[i].EasingLeft; // ... begin counting from clip's beginning and end (right) of left ease long easerFrame = arrClips2[i].EasingLeft; var index = i; // ... walk backward until easing is used up while (curFrame > easeEndAbs && index > 0) { index--; long curClipLen = arrClips2[index].LengthFrameCalcNoEasing; long easerFrame1 = easerFrame - curClipLen; long easerFrame2 = easerFrame; long easerOffset = 0; // ... when offset is needed, when curClipLen (clip being audio-ed) is longer than the easing. Easing audio will begin at the right side of this clip using the offset if (easerFrame1 < 0) { easerOffset = -easerFrame1; easerFrame1 = 0; } arrClips2[index].MixesAudioFromVideo.Add(new VideoEasingAudioToMix { ClipVarName = arrClips2[i].VarName, FrameStart = easerFrame1, FrameEnd = easerFrame2, FrameOffset = easerOffset, }); curFrame -= curClipLen; easerFrame -= curClipLen; } } if (arrClips2[i].EasingRight > 0) { var curFrame = curFrameEnd; long easeEndAbs = curFrame + arrClips2[i].EasingRight; // ... begin counting from clip's end and beginning (left) of right ease long easerFrame = arrClips2[i].LengthFrameCalc - arrClips2[i].EasingRight; var index = i; // ... walk forward until easing is used up while (curFrame < easeEndAbs && index < arrClips2.Length - 1) { index++; long curClipLen = arrClips2[index].LengthFrameCalcNoEasing; long easerFrame1 = easerFrame; long easerFrame2 = easerFrame + curClipLen; // ... when curClipLen (the clip being audio-ed) exceeds the overflow. Overflow is small and overflows in just the first part of the clip if (easerFrame2 > arrClips2[i].FrameEnd) { easerFrame2 = arrClips2[i].FrameEnd; } arrClips2[index].MixesAudioFromVideo.Add(new VideoEasingAudioToMix { ClipVarName = arrClips2[i].VarName, FrameStart = easerFrame1, FrameEnd = easerFrame2, FrameOffset = 0, }); curFrame += curClipLen; easerFrame += curClipLen; } } } var statVideos = arrClips2; //... this is important to reduce AVS overhead var firstStatCandidate = arrClips.FirstOrDefault(x => x.IsPixelTypeStandard); if (firstStatCandidate != null) { statVideos = new[] { new VideoClipRenderable { VideoFile = fileList.FirstOrDefault(f => f.FileName == firstStatCandidate.FileName) } } } ; //... this is more important when project was cropped, b/c for cropped projects the clip marked // as IsPixelTypeStandard can easily be outside if (proj.PixelTypeStandardClip != null) { var videoFileForThisOne = fileList.FirstOrDefault(f => f.FileName == proj.PixelTypeStandardClip.FileName); if (videoFileForThisOne == null) { fileList.Add(videoFileForThisOne = new RenderableMediaFile { FileName = proj.PixelTypeStandardClip.FileName, VarName = proj.PixelTypeStandardClip.FileName.FilenameToVarName(), Type = GetRenderableVideoFileType(proj.PixelTypeStandardClip), }); } statVideos = new[] { new VideoClipRenderable { VideoFile = videoFileForThisOne } }; } // ... make file var names all unique foreach (var fileFile in fileList) { var nonUniques = fileList.Where(x => x != fileFile && x.VarName == fileFile.VarName); foreach (var nonUnique in nonUniques) { nonUnique.VarName += "__" + VidkaIO.MakeGuidWord(); } } return(new RenderableProject { Files = fileList, Clips = arrClips2, MaxLengthOfImageClip = maxLengthOfImageClip, StatVideos = statVideos, AudioClips = proj.ClipsAudio.Select(x => new AudioClipRenderable { FileName = x.FileName, FrameStart = x.FrameStart, FrameEnd = x.FrameEnd, FrameOffset = x.FrameOffset, PostOp = x.PostOp, }), }); }