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,
                }),
            };
        }
Exemple #2
0
        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,
                }),
            });
        }