File size: 9,116 Bytes
0ad74ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# 使用Gradio Python客户端构建FastAPI应用

Tags: CLIENT, API, WEB APP

在本博客文章中,我们将演示如何使用 `gradio_client` [Python库](getting-started-with-the-python-client/) 来以编程方式创建Gradio应用的请求,通过创建一个示例FastAPI Web应用。我们将构建的 Web 应用名为“Acappellify”,它允许用户上传视频文件作为输入,并返回一个没有伴奏音乐的视频版本。它还会显示生成的视频库。

**先决条件**

在开始之前,请确保您正在运行Python 3.9或更高版本,并已安装以下库:

- `gradio_client`
- `fastapi`
- `uvicorn`

您可以使用`pip`安装这些库:

```bash
$ pip install gradio_client fastapi uvicorn
```

您还需要安装ffmpeg。您可以通过在终端中运行以下命令来检查您是否已安装ffmpeg:

```bash
$ ffmpeg version
```

否则,通过按照这些说明安装ffmpeg [链接](https://www.hostinger.com/tutorials/how-to-install-ffmpeg)。

## 步骤1:编写视频处理函数

让我们从似乎最复杂的部分开始--使用机器学习从视频中去除音乐。

幸运的是,我们有一个现有的Space可以简化这个过程:[https://huggingface.co/spaces/abidlabs/music-separation](https://huggingface.co/spaces/abidlabs/music-separation)。该空间接受一个音频文件,并生成两个独立的音频文件:一个带有伴奏音乐,一个带有原始剪辑中的其他所有声音。非常适合我们的客户端使用!

打开一个新的Python文件,比如`main.py`,并通过从`gradio_client`导入 `Client` 类,并将其连接到该Space:

```py
from gradio_client import Client

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

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

所需的代码仅如上所示--请注意,API端点返回一个包含两个音频文件(一个没有音乐,一个只有音乐)的列表,因此我们只返回列表的第一个元素。

---

**注意**:由于这是一个公共Space,可能会有其他用户同时使用该Space,这可能导致速度较慢。您可以使用自己的[Hugging Face token](https://huggingface.co/settings/tokens)复制此Space,创建一个只有您自己访问权限的私有Space,并绕过排队。要做到这一点,只需用下面的代码替换上面的前两行:

```py
from gradio_client import Client

client = Client.duplicate("abidlabs/music-separation", hf_token=YOUR_HF_TOKEN)
```

其他的代码保持不变!

---

现在,当然,我们正在处理视频文件,所以我们首先需要从视频文件中提取音频。为此,我们将使用`ffmpeg`库,它在处理音频和视频文件时做了很多艰巨的工作。使用`ffmpeg`的最常见方法是通过命令行,在Python的`subprocess`模块中调用它:

我们的视频处理工作流包含三个步骤:

1. 首先,我们从视频文件路径开始,并使用`ffmpeg`提取音频。
2. 然后,我们通过上面的`acapellify()`函数传入音频文件。
3. 最后,我们将新音频与原始视频合并,生成最终的Acapellify视频。

以下是Python中的完整代码,您可以将其添加到`main.py`文件中:

```python
import subprocess

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_{video_path}"
    subprocess.call(['ffmpeg', '-y', '-i', video_path, '-i', new_audio, '-map', '0:v', '-map', '1:a', '-c:v', 'copy', '-c:a', 'aac', '-strict', 'experimental', f"static/{new_video}"])
    return new_video
```

如果您想了解所有命令行参数的详细信息,请阅读[ffmpeg文档](https://ffmpeg.org/ffmpeg.html),因为它们超出了本教程的范围。

## 步骤2: 创建一个FastAPI应用(后端路由)

接下来,我们将创建一个简单的FastAPI应用程序。如果您以前没有使用过FastAPI,请查看[优秀的FastAPI文档](https://fastapi.tiangolo.com/)。否则,下面的基本模板将看起来很熟悉,我们将其添加到`main.py`中:

```python
import os
from fastapi import FastAPI, File, UploadFile, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

app = FastAPI()
os.makedirs("static", exist_ok=True)
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")

videos = []

@app.get("/", response_class=HTMLResponse)
async def home(request: Request):
    return templates.TemplateResponse(
        "home.html", {"request": request, "videos": videos})

@app.post("/uploadvideo/")
async def upload_video(video: UploadFile = File(...)):
    new_video = process_video(video.filename)
    videos.append(new_video)
    return RedirectResponse(url='/', status_code=303)
```

在这个示例中,FastAPI应用程序有两个路由:`/``/uploadvideo/``/` 路由返回一个显示所有上传视频的画廊的HTML模板。

`/uploadvideo/` 路由接受一个带有`UploadFile`对象的 `POST` 请求,表示上传的视频文件。视频文件通过`process_video()`方法进行 "acapellify",并将输出视频存储在一个列表中,该列表在内存中存储了所有上传的视频。

请注意,这只是一个非常基本的示例,如果这是一个发布应用程序,则需要添加更多逻辑来处理文件存储、用户身份验证和安全性考虑等。

## 步骤3:创建一个FastAPI应用(前端模板)

最后,我们创建Web应用的前端。首先,在与`main.py`相同的目录下创建一个名为`templates`的文件夹。然后,在`templates`文件夹中创建一个名为`home.html`的模板。下面是最终的文件结构:

```csv
├── main.py
├── templates
│   └── home.html
```

将以下内容写入`home.html`文件中:

```html
<!DOCTYPE html> <html> <head> <title> 视频库 </title> <style>
body { font-family: sans-serif; margin: 0; padding: 0; background-color:
#f5f5f5; } h1 { text-align: center; margin-top: 30px; margin-bottom: 20px; }
.gallery { display: flex; flex-wrap: wrap; justify-content: center; gap: 20px;
padding: 20px; } .video { border: 2px solid #ccc; box-shadow: 0px 0px 10px
rgba(0, 0, 0, 0.2); border-radius: 5px; overflow: hidden; width: 300px;
margin-bottom: 20px; } .video video { width: 100%; height: 200px; } .video p {
text-align: center; margin: 10px 0; } form { margin-top: 20px; text-align:
center; } input[type="file"] { display: none; } .upload-btn { display:
inline-block; background-color: #3498db; color: #fff; padding: 10px 20px;
font-size: 16px; border: none; border-radius: 5px; cursor: pointer; }
.upload-btn:hover { background-color: #2980b9; } .file-name { margin-left: 10px;
} </style> </head> <body> <h1> 视频库 </h1> {% if videos %}
<div class="gallery"> {% for video in videos %} <div class="video">
<video controls> <source src="{{ url_for('static', path=video) }}"
type="video/mp4"> 您的浏览器不支持视频标签。 </video> <p>{{ video
}}</p> </div> {% endfor %} </div> {% else %} <p>
尚未上传任何视频。</p> {% endif %} <form action="/uploadvideo/"
method="post" enctype="multipart/form-data"> <label for="video-upload"
class="upload-btn"> 选择视频文件 </label> <input type="file" name="video"
id="video-upload"> <span class="file-name"></span> <button
type="submit" class="upload-btn"> 上传 </button> </form> <script> //
在表单中显示所选文件名 const fileUpload =
document.getElementById("video-upload"); const fileName =
document.querySelector(".file-name"); fileUpload.addEventListener("change", (e)
=> { fileName.textContent = e.target.files[0].name; }); </script> </body>
</html>
```

## 第4步:运行 FastAPI 应用

最后,我们准备好运行由 Gradio Python 客户端提供支持的 FastAPI 应用程序。

打开终端并导航到包含 `main.py` 文件的目录,然后在终端中运行以下命令:

```bash
$ uvicorn main:app
```

您应该会看到如下输出:

```csv
Loaded as API: https://abidlabs-music-separation.hf.space ✔
INFO:     Started server process [1360]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```

就是这样!开始上传视频,您将在响应中得到一些“acapellified”视频(处理时间根据您的视频长度可能需要几秒钟到几分钟)。以下是上传两个视频后 UI 的外观:

![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/acapellify.png)

如果您想了解如何在项目中使用 Gradio Python 客户端的更多信息,请[阅读专门的指南](/getting-started-with-the-python-client/)。