Ejemplo n.º 1
0
        private void MakeOutput(string originalAudioFile, string outputFilePath, string splitOutputFolder, YoutubeProcessRequest request)
        {
            if (File.Exists(outputFilePath))
            {
                File.Delete(outputFilePath);
            }
            Directory.CreateDirectory(Path.GetDirectoryName(outputFilePath));
            var stemFiles = Directory.GetFiles(splitOutputFolder, "*.mp3", SearchOption.AllDirectories)
                            .Select(sf => new StemFileInfo {
                FileName = Path.GetFileName(sf), FileNameWithoutExtension = Path.GetFileNameWithoutExtension(sf), FilePath = sf
            })
                            .ToList();

            if (request.Extension == ".mp4")
            {
                // Video
                var    video = YoutubeHelper.DownloadVideo(request.Vid, true);
                string audioFilepath;
                if (request.SubFormats != null && request.SubFormats.Count == 1)
                {
                    // Single audio file for the video
                    audioFilepath = stemFiles.FirstOrDefault(sf => sf.FileNameWithoutExtension == request.SubFormats[0])?.FilePath;
                }
                else
                {
                    // Multiple audio files for the video
                    audioFilepath = outputFilePath.Replace(".mp4", ".mp3");
                    MergeMp3(audioFilepath, stemFiles.Where(sf => request.SubFormats.Contains(sf.FileNameWithoutExtension)));
                }

                if (audioFilepath != null)
                {
                    var cmd         = $"ffmpeg -y -i \"{video.VideoFileFullPath}\" -i \"{audioFilepath}\" -c:v copy -c:s mov_text -map 0:v:0 -map 1:a:0 -map 0:s:0? \"{outputFilePath}\"";
                    var shellResult = ShellHelper.Execute(cmd);
                    if (shellResult.ExitCode != 0)
                    {
                        throw new Exception(shellResult.Output);
                    }
                }
            }
            else if (request.Extension == ".mp3")
            {
                // Return a single stem mp3 or merge multiple mp3s
                MakeMp3(outputFilePath, request, stemFiles);
            }
            else if (request.Extension == ".zip")
            {
                // ZIP multiple MP3s
                MakeZip(originalAudioFile, outputFilePath, request, stemFiles);
            }
        }
Ejemplo n.º 2
0
        public ProcessResponse Process(YoutubeProcessRequest request)
        {
            var mainSw   = Stopwatch.StartNew();
            var ip       = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
            var logEntry = new YoutubeOutputLogEntry()
            {
                StartTime   = DateTime.Now,
                Vid         = request.Vid,
                Config      = $"{request.BaseFormat}{(request.Options.IncludeHighFrequencies ? "-hf" : "")}{request.Extension}",
                IpAddress   = ip,
                GeoLocation = GeoLocationHelper.GetGeoLocation(ip),
                Cache       = "Miss"
            };
            // 0. Check output cache
            var outputFilename = GetOutputFileName(request.Vid, request.BaseFormat, request.SubFormats, request.Extension, request.Options.IncludeHighFrequencies);
            var outputFilePath = $"{Output_Root}/yt/{outputFilename}";

            if (File.Exists(outputFilePath))
            {
                logEntry.Cache         = "L1 HIT";
                logEntry.Success       = true;
                logEntry.TimeToProcess = (int)mainSw.Elapsed.TotalSeconds;
                _logger.LogInformation($"Output cache hit: {outputFilePath}");
                return(new ProcessResponse()
                {
                    FileId = outputFilename, LogEntry = logEntry
                });
            }

            // Check processing cache, avoid duplicate requests to run
            var now = DateTime.UtcNow;

            if (_processing.TryGetValue(outputFilename, out DateTime startDate))
            {
                var startedSecondsAgo = (now - startDate).TotalSeconds;
                if (startedSecondsAgo < 1800)
                {
                    return(new ProcessResponse()
                    {
                        Error = $"File {outputFilename} is being processed, started {startedSecondsAgo:N0} seconds ago. Try again later in few more minutes..."
                    });
                }
            }
            _processing[outputFilename] = now;

            // 1. Get video title and duration
            var info = YoutubeHelper.GetVideoInfo(request.Vid);

            if (info.DurationSeconds > Max_Duration_Seconds)
            {
                return(new ProcessResponse()
                {
                    Error = $"Cannot process videos longer than {Max_Duration_Seconds} seconds"
                });
            }
            logEntry.Title    = info.Filename;
            logEntry.Duration = info.DurationSeconds;
            LogStart(request, info);

            // 2. Download Audio
            var audio = YoutubeHelper.DownloadAudio(request.Vid);

            // 3. Split
            var sw = Stopwatch.StartNew();
            var splitOutputFolder = GetAudioSplitOutputFolder(request);
            int fileCount         = Directory.Exists(splitOutputFolder) ? Directory.GetFiles(splitOutputFolder, "*.mp3", SearchOption.AllDirectories).Length : 0;

            if (fileCount == int.Parse(request.BaseFormat.Substring(0, 1)))
            {
                logEntry.Cache = "L2 HIT";
                _logger.LogInformation("Split output cache hit");
            }
            else
            {
                if (fileCount > 0)
                {
                    _logger.LogInformation($"Deleting folder {splitOutputFolder}");
                    Directory.Delete(splitOutputFolder, true);
                }
                // Create the directory to avoid File exists error on spleeter separate process (probably because of missing exist_ok=True parameter in https://github.com/deezer/spleeter/blob/42d476f6fa8d06f498389d1e620d2f1f59565f51/spleeter/audio/ffmpeg.py#L108)
                Directory.CreateDirectory(Path.Combine(splitOutputFolder, request.Vid));
                // Execute the split
                var splitResult = SpliterHelper.Split(audio.AudioFileFullPath, splitOutputFolder, request, isBatch: false);
                _logger.LogInformation($"Separation for {request.Vid}: {(splitResult.ExitCode == 0 ? "Successful" : "Failed")}\n\tDuration: {info.Duration}\n\tProcessing time: {sw.Elapsed:hh\\:mm\\:ss}");
                logEntry.TimeToSeparate = (int)sw.Elapsed.TotalSeconds;
                logEntry.Success        = splitResult.ExitCode == 0;
                logEntry.Errors         = string.Join(", ", splitResult.Errors);
                if (splitResult.ExitCode != 0)
                {
                    _processing.TryRemove(outputFilename, out _);
                    logEntry.TimeToProcess = (int)mainSw.Elapsed.TotalSeconds;
                    return(new ProcessResponse()
                    {
                        Error = $"spleeter separate command exited with code {splitResult.ExitCode}\nMessages: {splitResult.Output}.", LogEntry = logEntry
                    });
                }
            }
            sw.Stop();

            // 4. Make output
            MakeOutput(audio.AudioFileFullPath, outputFilePath, splitOutputFolder, request);

            _processing.TryRemove(outputFilename, out _);
            logEntry.Success       = true;
            logEntry.TimeToProcess = (int)mainSw.Elapsed.TotalSeconds;
            return(new ProcessResponse()
            {
                FileId = outputFilename,
                Speed = sw.Elapsed.TotalSeconds == 0 ? null : $"{info.DurationSeconds / sw.Elapsed.TotalSeconds:N1}x",
                TotalTime = sw.Elapsed.ToString("hh\\:mm\\:ss"),
                LogEntry = logEntry
            });
        }