| 1 | # frozen_string_literal: true |
| 2 | |
| 3 | # Convert YouTube video to audio. |
| 4 | class YoutubeToAudioJob < ApplicationJob |
| 5 | queue_as :default |
| 6 | |
| 7 | def perform(song_provider_id) |
| 8 | @provider = SongProvider.find_by(id: song_provider_id, provider_type: :youtube) |
| 9 | Sidekiq.logger.info('Starting YouTube to audio conversion...') |
| 10 | return if @provider.nil? |
| 11 | |
| 12 | # Do the split if the file is already attached. |
| 13 | if @provider.audio_file.present? && @provider.audio_file.source_file.attached? |
| 14 | SplitfireJob.perform_later(@provider.audio_file.id) |
| 15 | return |
| 16 | end |
| 17 | |
| 18 | prepare_environments |
| 19 | start_processing |
| 20 | end |
| 21 | |
| 22 | private |
| 23 | |
| 24 | def prepare_environments |
| 25 | Sidekiq.logger.info('Preparing environments...') |
| 26 | @youtube_video_id = @provider.provider_id |
| 27 | @youtube_video_url = @provider.preview_url |
| 28 | @audio_output_file_location = "output/#{@youtube_video_id}.mp3" |
| 29 | end |
| 30 | |
| 31 | def start_processing |
| 32 | change_working_directory |
| 33 | download_and_attach |
| 34 | split |
| 35 | end |
| 36 | |
| 37 | def change_working_directory |
| 38 | Sidekiq.logger.info('Changing working directory...') |
| 39 | system('echo $PWD') |
| 40 | Dir.chdir(ENV['YOUTUBE_DL_WORKING_DIRECTORY']) |
| 41 | broadcast_progress(15) |
| 42 | end |
| 43 | |
| 44 | def download_and_attach |
| 45 | Sidekiq.logger.info('Downloading and attaching...') |
| 46 | video_output_file_format = "output/#{@youtube_video_id}.%(ext)s" |
| 47 | system("yt-dlp --extract-audio --audio-format mp3 --output \"#{video_output_file_format}\" #{@youtube_video_url}") |
| 48 | attach |
| 49 | broadcast_progress(30) |
| 50 | end |
| 51 | |
| 52 | def attach |
| 53 | video_title = `yt-dlp --get-title #{@youtube_video_url}` |
| 54 | audio_output_file = File.open(@audio_output_file_location) |
| 55 | |
| 56 | # Attach audio |
| 57 | @provider.audio_file.source_file.attach(io: audio_output_file, filename: video_title) |
| 58 | return unless @provider.audio_file.save |
| 59 | |
| 60 | @provider.audio_file.update(status: :done) |
| 61 | system("rm #{@audio_output_file_location}") |
| 62 | end |
| 63 | |
| 64 | def split |
| 65 | Sidekiq.logger.info('Splitting...') |
| 66 | @provider.audio_file.update(status: :splitting) |
| 67 | broadcast_progress(50) |
| 68 | SplitfireJob.perform_later(@provider.audio_file.id) |
| 69 | end |
| 70 | |
| 71 | def broadcast_progress(progress) |
| 72 | @provider.audio_file.update(progress: progress) |
| 73 | ActionCable.server.broadcast('YoutubeToAudioChannel', @provider.as_json) |
| 74 | end |
| 75 | end |