File size: 4,359 Bytes
517cc63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5d1198f
517cc63
 
5d1198f
517cc63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
from gradio_client import Client
import yt_dlp # pip install yt-dlp

import subprocess

import os
from pathlib import Path
import gradio as gr
import shutil
import random
from theme import theme

VIDEO_DIRECTORY = "videos"


client = Client("abidlabs/music-separation")

def acapellify(audio_path):
    result = client.predict(audio_path, api_name="/predict")
    return result[0]

# based on https://github.com/gradio-app/gradio/blob/bebfb72b353a4280155cf7070441fc476ac10172/guides/06_client-libraries/fastapi-app-with-the-gradio-client.md
def process_video(video_path):
    old_audio = os.path.basename(video_path).split(".")[0] + ".m4a"
    subprocess.run(['ffmpeg', '-y', '-i', video_path, '-vn', '-acodec', 'copy', old_audio])
    
    new_audio = acapellify(old_audio)
    
    new_video = f"acap_{Path(video_path).name}"
    new_video_path = f"{VIDEO_DIRECTORY}/{new_video}"
    subprocess.call(['ffmpeg', '-y', '-i', video_path, '-i', new_audio, '-map', '0:v', '-map', '1:a', '-c:v', 'copy', '-c:a', 'aac', '-strict', 'experimental', new_video_path])

    # remove old audio and video
    os.remove(old_audio)
    os.remove(video_path)

    new_audio_path = f"{VIDEO_DIRECTORY}/{old_audio}"
    shutil.move(new_audio, new_audio_path)

    return new_video_path, new_audio_path

# filename default value will return name of video on youtube
def download_yt_url(url: str, filename: str = "%(title)s", format = 'mp4'):

    output_path = f"{VIDEO_DIRECTORY}/{filename}.{format}"

    # restrict video length so one user doesn't take up all our bandwidth
    def video_filter(info):
        MAX_DURATION = 10*60
        duration = info.get('duration')
        if duration and duration > MAX_DURATION:
            raise Exception(f'The video is too long at {duration}s, choose a video less than {MAX_DURATION}s')

    ydl_opts = {
        'match_filter': video_filter,
        'format': f'{format}/bestaudio',
        'outtmpl': output_path,
    }

    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        error_code = ydl.download([url])
        #info = ydl.extract_info(url, extra_info={"output_path": output_path})

    if error_code:
        raise Exception(f"Failed to download video, error code: {error_code}")
    
    return output_path

def wrap_html(yt_url):
    return f"""<h1><center>Original Video: <a href='{yt_url}'>{yt_url}</a></center><h1>"""

# ideally yt_url should be validated
def acapellify_url(yt_url, gr_request: gr.Request):
    
    # example filename: https://www.youtube.com/watch?v=TasKo5HHWb4 -> TasKo5HHWb4
    filename = yt_url.rsplit("=", 1)[-1]

    video_path = download_yt_url(yt_url, filename)

    new_video_path, new_audio_path = process_video(video_path)
    return new_video_path, new_audio_path, wrap_html(yt_url)


def load_mystery_video(gr_request: gr.Request):

    video_paths = list(Path(VIDEO_DIRECTORY).glob("*.mp4"))

    selected_video = video_paths[random.randrange(len(video_paths))]

    file_name = selected_video.name.replace("acap_", "").split(".", 1)[0]
    selected_audio = Path(VIDEO_DIRECTORY) / f"{file_name}.m4a"
    yt_url = f"https://www.youtube.com/watch?v={file_name}"

    selected_video = str(selected_video)
    selected_audio = str(selected_audio)

    return selected_video, selected_audio, wrap_html(yt_url)


with open("header.md", "r") as markdown_file:
    markdown_text = markdown_file.read()

with gr.Blocks(theme=theme) as demo:

    with gr.Row():
        header = gr.Markdown(markdown_text)
    with gr.Row().style():
        
        with gr.Column(scale=0.4, variant="panel"):
            input_url = gr.Textbox(label="Youtube URL")
            
            process_video_btn = gr.Button("Acapellify", variant="primary")
            mystery_btn = gr.Button("Mysterious Video")

            static_path_display = gr.HTML(label="Output File Paths", visible=True)

        with gr.Column(scale=0.6, variant="panel"):
            output_video = gr.Video(label="Acapellified Video")
            output_audio = gr.Audio(label="Acapellified Audio")

    process_video_btn.click(fn=acapellify_url, inputs=[input_url], outputs=[output_video, output_audio, static_path_display])
    mystery_btn.click(fn=load_mystery_video, inputs=[], outputs=[output_video, output_audio, static_path_display])

if __name__ == "__main__":
    os.makedirs(VIDEO_DIRECTORY, exist_ok=True)
    demo.launch()