1. Gradio 客户端和 Lite
  2. 使用Gradio客户端的Fastapi应用

使用Gradio Python客户端构建Web应用程序

在这篇博客文章中,我们将演示如何使用gradio_client Python库,通过使用FastAPI创建一个端到端的示例Web应用程序,使开发人员能够以编程方式向Gradio应用程序发出请求。我们将构建的Web应用程序名为“Acapellify”,它将允许用户上传视频文件作为输入,并返回一个没有乐器音乐的视频版本。它还将显示生成的视频库。

先决条件

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

  • gradio_client
  • fastapi
  • uvicorn

你可以从pip安装这些库:

$ pip install gradio_client fastapi uvicorn

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

$ ffmpeg version

否则,请按照这些说明安装ffmpeg。

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

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

幸运的是,有一个现有的Space我们可以用来简化这个过程:https://huggingface.co/spaces/abidlabs/music-separation。这个Space接收一个音频文件并生成两个独立的音频文件:一个包含乐器音乐,另一个包含原始剪辑中的所有其他声音。非常适合与我们的客户一起使用!

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

from gradio_client import Client, handle_file

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

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

这就是所需的全部代码——注意API接口返回了两个音频文件(一个没有音乐,另一个只有音乐)在一个列表中,所以我们只返回列表的第一个元素。


注意:由于这是一个公共空间,可能还有其他用户也在使用这个空间,这可能会导致体验变慢。你可以使用自己的Hugging Face token复制这个空间,并创建一个只有你可以访问的私人空间,从而绕过队列。要做到这一点,只需将上面的前两行替换为:

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. 最后,我们将新的音频与原始视频结合,生成最终的纯人声视频。

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

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文档,因为它们超出了本教程的范围。

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

接下来,我们将创建一个简单的FastAPI应用程序。如果你以前没有使用过FastAPI,请查看优秀的FastAPI文档。否则,这个基本模板,我们添加到main.py中,看起来会非常熟悉:

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(...)):
    video_path = video.filename
    with open(video_path, "wb+") as fp:
        fp.write(video.file.read())

    new_video = process_video(video.filename)
    videos.append(new_video)
    return RedirectResponse(url='/', status_code=303)

在这个例子中,FastAPI 应用有两个路由://uploadvideo/

/ 路由返回一个显示所有上传视频画廊的HTML模板。

/uploadvideo/ 路由接受一个带有 UploadFile 对象的 POST 请求,该对象表示上传的视频文件。视频文件通过 process_video() 方法进行“无伴奏处理”,输出视频存储在内存中保存所有上传视频的列表中。

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

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

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

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

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

<!DOCTYPE html> <html> <head> <title>Video Gallery</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>Video Gallery</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"> Your browser does not support the video tag. </video>
<p>{{ video }}</p> </div> {% endfor %} </div> {% else %} <p>No
videos uploaded yet.</p> {% endif %} <form action="/uploadvideo/"
method="post" enctype="multipart/form-data"> <label for="video-upload"
class="upload-btn">Choose video file</label> <input type="file"
name="video" id="video-upload"> <span class="file-name"></span> <button
type="submit" class="upload-btn">Upload</button> </form> <script> //
Display selected file name in the form 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的目录。然后在终端中运行以下命令:

$ uvicorn main:app

你应该会看到一个看起来像这样的输出:

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)

就这样!开始上传视频,你会得到一些“无伴奏”视频作为响应(处理时间可能需要几秒到几分钟,取决于视频的长度)。以下是上传两个视频后用户界面的样子:

如果您想了解更多关于如何在项目中使用Gradio Python客户端的信息,请阅读专用指南