def handleDLToMp4(self): try: appStatus.set('[1/2] Downloading...') root.update() getYTVideo = YouTube(ytLink.get()) composedFilePath = f'{self.usrDownloadPath}{sep}{getYTVideo.title}.mp4' getYTVideo.streams.filter(adaptive=True, type='video').first().download( self.usrDownloadPath, filename='tmpVidFile') getYTVideo.streams.filter(adaptive=True, type='audio').first().download( self.usrDownloadPath, filename='tmpAudFile') tmpVideoFile = VideoFileClip(self.tmpVideoFilePath) tmpAudioFile = AudioFileClip(self.tmpAudioFilePath) appStatus.set('[2/2] Converting & mounting file...') ytLink.set('This step may take some minutes') root.update() mountClip = tmpVideoFile.set_audio(tmpAudioFile) mountClip.write_videofile(composedFilePath, fps=30) tmpVideoFile.close() tmpAudioFile.close() remove(self.tmpVideoFilePath) remove(self.tmpAudioFilePath) appStatus.set('Done!') ytLink.set('Check your "Downloads" directory.') root.update() except Exception as e: print(e) appStatus.set('Whoops, something went wrong!') ytLink.set(value='Invalid link!') root.update()
def get_audio(self): created = False audio = Audio() self._audio_file = f'{self.filename}.mp3' clip = AudioFileClip(self._video_file) clip.write_audiofile(self._audio_file) clip.close() try: audio.mp3 = File(open(self._audio_file, mode='rb')) print('File was successfully uploaded.') audio.name = self._title audio.api = 'PyTube API' try: audio.save() except: print('Object was not saved!') created = True except Exception: print('File not found!') self._highlight_title() if created: return created, audio else: return created, None
def get_mp3(url): youtube_video = YouTube(url) title = special_characters(youtube_video.title) # Converting MP4 to MP3 mp3_file = f'{title}.mp3' mp4_file = f'{title}.mp4' youtube_video.streams.filter(only_audio=True).first().download() mp3_file_path = os.path.join(BASE_DIR, mp3_file) mp4_file_path = os.path.join(BASE_DIR, mp4_file) clip = AudioFileClip(mp4_file_path) clip.write_audiofile(mp3_file_path) clip.close() # os.remove(mp4_file_path) audio = Audio() audio.mp3 = File(open(mp3_file, mode='rb')) # audio.image = img audio.image = youtube_video.thumbnail_url audio.name = youtube_video.title audio.save() if mp4_file in os.listdir(BASE_DIR): os.remove(mp4_file) if mp3_file in os.listdir(BASE_DIR): os.remove(mp3_file)
def download_Audio(self): yt_link = self.linkAudio.get() try: if yt_link == '' or yt_link == None: messagebox.showerror(f"Aviso", "Campo Vazio") else: path_audio = 'C:/Temp/Musicas' yt = YouTube(yt_link) audio = yt.streams.filter(only_audio=True)[0] mp4_file = audio.download(path_audio) mp3_file = audio.default_filename[:-4] + ".mp3" videoClip = AudioFileClip(mp4_file, fps=44100) audioclip = videoClip audioclip.write_audiofile(path_audio + '/' + mp3_file, fps=44100) os.remove(path_audio + '/' + audio.default_filename) videoClip.close() audioclip.close() messagebox.showinfo(f"Aviso", "Download Completo!") self.linkAudio.delete(0, END) except: messagebox.showerror(f"Erro", "Arquivo invalido para Download!")
def convert(self): audio = askopenfilenames() try: for num in audio: mp4_file = num mp3_file = mp4_file[:-4] + ".mp3" musica = AudioFileClip(mp4_file, fps=44100) audioClip = musica audioClip.write_audiofile(mp3_file, fps=44100, logger="bar") if num[:-4] + ".mp4" == num: os.remove(num) musica.close() audioClip.close() messagebox.showinfo(f"Aviso", "Convertido para MP3 com sucesso!") except: messagebox.showerror(f"Erro", "Arquivo invalido para converter!")
def download_audio(self, vid, qual, target_dir, ind, n): if qual == "Highest": path = vid.streams.get_audio_only( subtype="webm").download(target_dir) for stream in vid.streams: if stream.mime_type == "audio/webm" and stream.abr == qual: path = stream.download(target_dir) break else: path = vid.streams.get_audio_only( subtype="webm").download(target_dir) new_path = path[:-5] + ".mp3" file = AudioFileClip(path) self.message_label.setText( f"Converting audio stream to mp3.. ({ind + 1} of {n})") file.write_audiofile(new_path) file.close() os.remove(path) metadata = vid.metadata.metadata f = music_tag.load_file(new_path) f['artist'] = (metadata[0]['Artist'] if len(metadata) > 0 and metadata[0].get('Artist') is not None else vid.author) f['comment'] = vid.description f['compilation'] = False f['composer'] = f['artist'] f['tracktitle'] = (metadata[0]['Song'] if len(metadata) > 0 and metadata[0].get('Song') is not None else vid.title) f['year'] = vid.publish_date.year f.save() return new_path
class VideoFileClip(VideoClip): """ A video clip originating from a movie file. For instance: :: >>> clip = VideoFileClip("myHolidays.mp4") >>> clip.close() >>> with VideoFileClip("myMaskVideo.avi") as clip2: >>> pass # Implicit close called by context manager. Parameters ---------- filename: The name of the video file, as a string or a path-like object. It can have any extension supported by ffmpeg: .ogv, .mp4, .mpeg, .avi, .mov etc. has_mask: Set this to 'True' if there is a mask included in the videofile. Video files rarely contain masks, but some video codecs enable that. For instance if you have a MoviePy VideoClip with a mask you can save it to a videofile with a mask. (see also ``VideoClip.write_videofile`` for more details). audio: Set to `False` if the clip doesn't have any audio or if you do not wish to read the audio. target_resolution: Set to (desired_width, desired_height) to have ffmpeg resize the frames before returning them. This is much faster than streaming in high-res and then resizing. If either dimension is None, the frames are resized by keeping the existing aspect ratio. resize_algorithm: The algorithm used for resizing. Default: "bicubic", other popular options include "bilinear" and "fast_bilinear". For more information, see https://ffmpeg.org/ffmpeg-scaler.html fps_source: The fps value to collect from the metadata. Set by default to 'fps', but can be set to 'tbr', which may be helpful if you are finding that it is reading the incorrect fps from the file. pixel_format Optional: Pixel format for the video to read. If is not specified 'rgb24' will be used as the default format unless ``has_mask`` is set as ``True``, then 'rgba' will be used. Attributes ---------- filename: Name of the original video file. fps: Frames per second in the original file. Read docs for Clip() and VideoClip() for other, more generic, attributes. Lifetime -------- Note that this creates subprocesses and locks files. If you construct one of these instances, you must call close() afterwards, or the subresources will not be cleaned up until the process ends. If copies are made, and close() is called on one, it may cause methods on the other copies to fail. """ @convert_path_to_string("filename") def __init__( self, filename, decode_file=False, has_mask=False, audio=True, audio_buffersize=200000, target_resolution=None, resize_algorithm="bicubic", audio_fps=44100, audio_nbytes=2, fps_source="fps", pixel_format=None, ): VideoClip.__init__(self) # Make a reader if not pixel_format: pixel_format = "rgba" if has_mask else "rgb24" self.reader = FFMPEG_VideoReader( filename, decode_file=decode_file, pixel_format=pixel_format, target_resolution=target_resolution, resize_algo=resize_algorithm, fps_source=fps_source, ) # Make some of the reader's attributes accessible from the clip self.duration = self.reader.duration self.end = self.reader.duration self.fps = self.reader.fps self.size = self.reader.size self.rotation = self.reader.rotation self.filename = filename if has_mask: self.make_frame = lambda t: self.reader.get_frame(t)[:, :, :3] def mask_make_frame(t): return self.reader.get_frame(t)[:, :, 3] / 255.0 self.mask = VideoClip(is_mask=True, make_frame=mask_make_frame).with_duration( self.duration) self.mask.fps = self.fps else: self.make_frame = lambda t: self.reader.get_frame(t) # Make a reader for the audio, if any. if audio and self.reader.infos["audio_found"]: self.audio = AudioFileClip( filename, buffersize=audio_buffersize, fps=audio_fps, nbytes=audio_nbytes, ) def __deepcopy__(self, memo): """Implements ``copy.deepcopy(clip)`` behaviour as ``copy.copy(clip)``. VideoFileClip class instances can't be deeply copied because the locked Thread of ``proc`` isn't pickleable. Without this override, calls to ``copy.deepcopy(clip)`` would raise a ``TypeError``: ``` TypeError: cannot pickle '_thread.lock' object ``` """ return self.__copy__() def close(self): """Close the internal reader.""" if self.reader: self.reader.close() self.reader = None try: if self.audio: self.audio.close() self.audio = None except AttributeError: # pragma: no cover pass
class VideoFileClip(VideoClip): """ A video clip originating from a movie file. For instance: :: >>> clip = VideoFileClip("myHolidays.mp4") >>> clip.close() >>> with VideoFileClip("myMaskVideo.avi") as clip2: >>> pass # Implicit close called by contex manager. Parameters ------------ filename: The name of the video file. It can have any extension supported by ffmpeg: .ogv, .mp4, .mpeg, .avi, .mov etc. has_mask: Set this to 'True' if there is a mask included in the videofile. Video files rarely contain masks, but some video codecs enable that. For istance if you have a MoviePy VideoClip with a mask you can save it to a videofile with a mask. (see also ``VideoClip.write_videofile`` for more details). audio: Set to `False` if the clip doesn't have any audio or if you do not wish to read the audio. target_resolution: Set to (desired_height, desired_width) to have ffmpeg resize the frames before returning them. This is much faster than streaming in high-res and then resizing. If either dimension is None, the frames are resized by keeping the existing aspect ratio. resize_algorithm: The algorithm used for resizing. Default: "bicubic", other popular options include "bilinear" and "fast_bilinear". For more information, see https://ffmpeg.org/ffmpeg-scaler.html fps_source: The fps value to collect from the metadata. Set by default to 'tbr', but can be set to 'fps', which may be helpful if importing slow-motion videos that get messed up otherwise. Attributes ----------- filename: Name of the original video file. fps: Frames per second in the original file. Read docs for Clip() and VideoClip() for other, more generic, attributes. Lifetime -------- Note that this creates subprocesses and locks files. If you construct one of these instances, you must call close() afterwards, or the subresources will not be cleaned up until the process ends. If copies are made, and close() is called on one, it may cause methods on the other copies to fail. """ def __init__(self, filename, has_mask=False, audio=True, audio_buffersize = 200000, target_resolution=None, resize_algorithm='bicubic', audio_fps=44100, audio_nbytes=2, verbose=False, fps_source='tbr'): VideoClip.__init__(self) # Make a reader pix_fmt= "rgba" if has_mask else "rgb24" self.reader = FFMPEG_VideoReader(filename, pix_fmt=pix_fmt, target_resolution=target_resolution, resize_algo=resize_algorithm, fps_source=fps_source) # Make some of the reader's attributes accessible from the clip self.duration = self.reader.duration self.end = self.reader.duration self.fps = self.reader.fps self.size = self.reader.size self.rotation = self.reader.rotation self.filename = self.reader.filename if has_mask: self.make_frame = lambda t: self.reader.get_frame(t)[:,:,:3] mask_mf = lambda t: self.reader.get_frame(t)[:,:,3]/255.0 self.mask = (VideoClip(ismask = True, make_frame = mask_mf) .set_duration(self.duration)) self.mask.fps = self.fps else: self.make_frame = lambda t: self.reader.get_frame(t) # Make a reader for the audio, if any. if audio and self.reader.infos['audio_found']: self.audio = AudioFileClip(filename, buffersize= audio_buffersize, fps = audio_fps, nbytes = audio_nbytes) def close(self): """ Close the internal reader. """ if self.reader: self.reader.close() self.reader = None try: if self.audio: self.audio.close() self.audio = None except AttributeError: pass
try: my_abs_path = my_file.resolve(strict=True) except FileNotFoundError: # doesn't exist print('ERROR. \n' + ogVid.title + ' was not downloaded') errorList.append(ogVid.title) else: #exists #open the video with moviepy and save it to clip the weird silence off of the end clip = AudioFileClip(getcwd() + '/.trash/' + vidTitle + '.mp4') ffmpeg_audiowrite(clip, getcwd() + '/MusicFiles/' + vidTitle + '.mp4', fps=44100, nbytes=4, buffersize=2000, codec='aac') clip.close() print(ogVid.title + ' DOWNLOADED') file.close() #delete all the useless files in the .trash folder filelist = [f for f in listdir(getcwd() + '/.trash/') if f.endswith('.mp4')] for f in filelist: remove(path.join(getcwd() + '/.trash/', f)) print('\nPlaylist to MP4 EXITED.') print('Program ended: ' + datetime.now().strftime("%Y-%m-%d %H:%M:%S") + '\n') #print out a list of videos that were not downloaded if len(errorList) > 0: print('WARNING. ' + str(len(errorList)) + ' videos not downloaded.') for x in errorList: print(x + ' was not downloaded.')
class VideoFileClip(VideoClip): """ A video clip originating from a movie file. For instance: :: >>> clip = VideoFileClip("myHolidays.mp4") >>> clip.close() >>> with VideoFileClip("myMaskVideo.avi") as clip2: >>> pass # Implicit close called by context manager. Parameters ------------ filename: The name of the video file. It can have any extension supported by ffmpeg: .ogv, .mp4, .mpeg, .avi, .mov etc. has_mask: Set this to 'True' if there is a mask included in the videofile. Video files rarely contain masks, but some video codecs enable that. For istance if you have a MoviePy VideoClip with a mask you can save it to a videofile with a mask. (see also ``VideoClip.write_videofile`` for more details). audio: Set to `False` if the clip doesn't have any audio or if you do not wish to read the audio. target_resolution: Set to (desired_height, desired_width) to have ffmpeg resize the frames before returning them. This is much faster than streaming in high-res and then resizing. If either dimension is None, the frames are resized by keeping the existing aspect ratio. resize_algorithm: The algorithm used for resizing. Default: "bicubic", other popular options include "bilinear" and "fast_bilinear". For more information, see https://ffmpeg.org/ffmpeg-scaler.html fps_source: The fps value to collect from the metadata. Set by default to 'tbr', but can be set to 'fps', which may be helpful if importing slow-motion videos that get messed up otherwise. Attributes ----------- filename: Name of the original video file. fps: Frames per second in the original file. Read docs for Clip() and VideoClip() for other, more generic, attributes. Life time -------- Note that this creates sub-processes and locks files. If you construct one of these instances, you must call close() afterwards, or the sub-resources will not be cleaned up until the process ends. If copies are made, and close() is called on one, it may cause methods on the other copies to fail. """ def __init__(self, filename, has_mask=False, audio=True, audio_buffersize=200000, target_resolution=None, resize_algorithm='bicubic', audio_fps=44100, audio_nbytes=2, verbose=False, fps_source='tbr'): VideoClip.__init__(self) # Make a reader pix_fmt = "rgba" if has_mask else "rgb24" self.reader = FFMPEG_VideoReader(filename, pix_fmt=pix_fmt, target_resolution=target_resolution, resize_algo=resize_algorithm, fps_source=fps_source) # Make some of the reader's attributes accessible from the clip self.duration = self.reader.duration self.end = self.reader.duration self.fps = self.reader.fps self.size = self.reader.size self.rotation = self.reader.rotation self.filename = self.reader.filename if has_mask: self.make_frame = lambda t: self.reader.get_frame(t)[:, :, :3] mask_mf = lambda t: self.reader.get_frame(t)[:, :, 3] / 255.0 self.mask = (VideoClip( ismask=True, make_frame=mask_mf).set_duration(self.duration)) self.mask.fps = self.fps else: self.make_frame = lambda t: self.reader.get_frame(t) # Make a reader for the audio, if any. if audio and self.reader.infos['audio_found']: self.audio = AudioFileClip(filename, buffersize=audio_buffersize, fps=audio_fps, nbytes=audio_nbytes) def close(self): """ Close the internal reader. """ if self.reader: self.reader.close() self.reader = None try: if self.audio: self.audio.close() self.audio = None except AttributeError: pass
def mp3_converter(title, url): mp3_object = Audio() created = False mp3_id = None special_characters_flag = False file_name = title print('flag 3') print('flag 4') # Updating the title to compare it with the mp4 file that exist for it in this folder... title = special_characters(title) print('flag 5') mp3_file = f'{title}.mp3' mp4_file = f'{title}.mp4' # Converting MP4 to MP3 clip = AudioFileClip(mp4_file) clip.write_audiofile(mp3_file) clip.close() print('flag 6') try: # Opening the mp3 file to create an object to store to the database. mp3_object.mp3 = File(open(mp3_file, mode='rb')) mp3_object.name = file_name mp3_object.save() mp3_id = mp3_object.pk print('flag 7') # Deleting the downloaded file after uploading it to cloudinary here... if mp4_file in os.listdir(BASE_DIR): os.remove(mp4_file) if mp3_file in os.listdir(BASE_DIR): os.remove(mp3_file) created = True print('flag 8') except Exception: print("MP4 file cannot open properly") # Saving the object to the database. if not created: # Information that the object wasn't created successfully. We will use this value within the view.py to prevent # the programme from crashing. special_characters_flag = True # Now creating an object to inform administrator what to try and fix to improve the website's functionalities. error = TitleError() error.name = file_name error.url = str(url) error.email_sender() error.save() print('flag 9') print('flag 10') return mp3_id, special_characters_flag
def download(self): url = self.url_line_edit.text() target_dir = self.folder_line_edit.text() quality = str(self.quality_combo_box.currentText()) is_v, is_p = self.is_v(url), self.is_p(url) if is_p: playlist = pt.Playlist(url) iter_things = playlist.video_urls elif is_v: iter_things = [url] else: self.url_line_edit.setText("Please enter a valid url") return if not target_dir: self.folder_line_edit.setText("Please choose a directory") return if quality == SELECT_QUALITY_PROMPT_STRING: return self.title_label.setText("") self.title_label.setText("Downloading..") self.message_label.setHidden(False) self.quality_combo_box.setHidden(True) self.folder_line_edit.setHidden(True) self.queue_push_button.setHidden(True) self.select_folder_push_button.setHidden(True) self.url_line_edit.setHidden(True) self.search_push_button.setHidden(True) self.start_push_button.setHidden(True) n = len(iter_things) for ind, text in enumerate(iter_things): ext, _, _, qual, vora = quality.split(" ") vid = pt.YouTube(text, on_progress_callback=self.update_progress) if vora == "resolution": self.video_progress_bar.setHidden(False) self.message_label.setText( f"Downloading video.. ({ind + 1} of {n})") video_path, is_progressive = self.download_video( vid, ext, qual, target_dir) if not is_progressive: self.audio_progress_bar.setHidden(False) self.message_label.setText( f"Downloading audio.. ({ind + 1} of {n})") audio_path = self.download_audio(vid, "Highest", target_dir, ind, n) self.message_label.setText( f"Merging streams.. ({ind + 1} of {n})") v = VideoFileClip(video_path) a = AudioFileClip(audio_path) v = v.set_audio(a) self.message_label.setText( f"Writing to disk.. ({ind + 1} of {n})") v.write_videofile(f"{video_path[:-4]} - Output.mp4") v.close() a.close() os.remove(audio_path) os.remove(video_path) os.rename(f"{video_path[:-4]} - Output.mp4", f"{video_path[:-4]}.mp4") self.audio_progress_bar.setHidden(True) self.video_progress_bar.setHidden(True) elif vora == "bitrate": self.audio_progress_bar.setHidden(False) self.message_label.setText( f"Downloading audio stream.. ({ind + 1} of {n})") self.download_audio(vid, qual, target_dir, ind, n) self.audio_progress_bar.setHidden(True) self.title_label.setText("YouTube Downloader") self.message_label.setText("") self.message_label.setHidden(True) self.queue_push_button.setHidden(False) self.url_line_edit.setHidden(False) self.search_push_button.setHidden(False)
def _compile_worker(session_key: str, video_id: str) -> None: # Use this for conditional creation config = get_nosql_handler().get_video_config(video_id) session_clips = get_sql_handler().get_session_clips_by_session_key(session_key) for session_clip in session_clips: download_session_clip(session_clip, sync=True) session_audios = get_sql_handler().get_session_audio_by_session_key(session_key) session_audio = None if session_audios: session_audio = session_audios[0] download_session_audio(session_audio, sync=True) # Create VideoFileClips clips = [VideoFileClip(session_clip.local_file_path()) for session_clip in session_clips] total_duration = sum([clip.duration for clip in clips]) # Make all clips the same size final_w = min([clip.w for clip in clips]) final_h = min([clip.h for clip in clips]) clips = [resize(clip, newsize=(final_w, final_h)) for clip in clips] # Adding gamertag and logo to the video # gamertag = config.get('gamertag', '') # gamertag_position = config.get('gamertag_position', ['right', 'bottom']) # # if gamertag != '': # gamertag_clip = TextClip(txt='@'+gamertag, fontsize=50, font = 'Comfortaa', color='white') # gamertag_clip = gamertag_clip.set_duration(final.duration)\ # .margin(right=8,top = 8, left=8, bottom=8, opacity=0)\ # .set_position((gamertag_position[0], gamertag_position[1]) # === WATERMARK === logo_position = config.get('logo_position', ['left', 'top']) logo_clip = ImageClip('./reels/static/reels/reels-logo-white.png') logo_clip = resize(logo_clip, height=final_h / 5) try: logo_x = (0 if logo_position[0] == 'left' else final_w - logo_clip.w) logo_y = (0 if logo_position[1] == 'top' else final_h - logo_clip.h) except (KeyError, TypeError): logo_x, logo_y = 0, final_h - logo_clip.h logo_clip = logo_clip.set_pos((logo_x, logo_y)) clips = [CompositeVideoClip([clip, logo_clip.set_duration(clip.duration)]) for clip in clips] # Concatenate clips final = concatenate_videoclips(clips, method="compose") # Add audio, only if there is audio audio_clip = None if session_audio: audio_clip = AudioFileClip(session_audio.local_file_path()) audio_clip = audio_clip \ .set_start(config.get('audio_start', 0)) \ .set_end(config.get('audio_end', audio_clip.duration)) # Attach audio to video, but make it only as long as the videos are # TODO: Manage case where videos are longer than audio clip final = final.set_audio(audio_clip.set_duration(final.duration)) # If extra editing is enabled, do so if config.get('extras', False) and session_audio and get_file_type(session_audio.local_file_path()) == 'wav': fs, data = read(session_audio.local_file_path()) data = data[:, 0] data = data[:len(data) - len(data) % 48000] data2 = np.mean(data.reshape(-1, int(48000 / 4)), axis=1) x = np.diff(data2, n=1) secs = np.where(x > 200)[0] t = list(secs[np.where(np.diff(secs) > 12)[0] + 1]) if np.diff(secs)[0] > 12: t.insert(0, secs[0]) for i in range(0, len(t)): t[i] /= 4 for i in t: tfreeze = i if tfreeze + 1.75 >= final.duration: break clip_before = final.subclip(t_end=tfreeze) clip_after = final.subclip(t_start=tfreeze + 1) clip = final.subclip(t_start=tfreeze, t_end=tfreeze + 1) if int(i) % 2 == 0: clip = clip.fl_image(invert_colors).crossfadein(0.5).crossfadeout(0.5) else: clip = clip.fx(vfx.painting, saturation=1.6, black=0.006).crossfadein(0.5).crossfadeout(0.5) final = concatenate_videoclips([clip_before, clip, clip_after]) else: pass # === Final Saving === video = get_sql_handler().get_video(video_id) final.write_videofile(filename=video.local_file_path(), verbose=True, codec="libx264", audio_codec='aac', temp_audiofile=f'temp-audio-{video.video_id}.m4a', remove_temp=True, preset="medium", ffmpeg_params=["-profile:v", "baseline", "-level", "3.0", "-pix_fmt", "yuv420p"]) # close local files because we don't need them anymore and so they can be removed later for clip in clips: clip.close() if audio_clip: audio_clip.close() # upload to cold storage save_video(video, sync=True, clean=False)