在线视频转音频 https://yttomp3.media/ 和 https://youtubetomp3converter.media/ 两个工具(目前已不能使用,使用Cobalt项目搭建的后端有问题,无法转换成MP3文件,计划停掉不再维护)开始是根据Cobalt提供的接口实现的,在这个项目升级之后关闭了免费的接口,所以需要自己拉取Git项目搭建一个后端服务。
一、服务平台选择
对比了下各个平台的费用,搭建后端服务的平台直接使用赞助Cobalt项目的RoyaleHosting,相比其他平台性价比最高,需要注意的是,在RoyaleHosting平台注册账号的时候不要使用iCloud的邮箱,iCloud屏蔽了这个平台的邮件发送服务,无法使用iCloud的邮箱激活账号,如果不慎使用iCloud邮箱,可以提一个Ticket(https://royalehosting.net/dashboard/tickets)给服务支持人员。
服务器的地址最好是选美国区域,如果选错了,也可以提一个Ticket去修改。
服务器的系统选择Ubuntu 22.04版本。
考虑到后续的访问量,选择4核4G内存的配置。
二、环境搭建配置
在创建服务钱,先购买一个域名,阿里云或namecheap都可以,配置下二级域名,比如购买的域名是xxx.com,二级域名参数配置成api.xxx.com,添加二级域名的A记录到购买的服务器IP地址。
按照Cobalt的文档操作:https://github.com/imputnet/cobalt/blob/main/docs/run-an-instance.md
1. 安装Docker
在 Ubuntu 20.04 上安装 Docker,可以按照以下步骤进行:
1.1 更新 apt 包索引
首先,更新系统的包索引,以确保你获得最新的软件包:
sudo apt update
1.2 安装依赖包
安装一些 Docker 所需的依赖包:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
1.3 添加 Docker 的官方 GPG 密钥
下载 Docker 的官方 GPG 密钥,以便验证安装包的签名:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
1.4 添加 Docker 仓库
将 Docker 的官方仓库添加到系统的 apt 源列表中:
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
1.5 更新 apt 包索引
再次更新 apt 包索引,以便使用 Docker 仓库中的软件包:
sudo apt update
1.6 安装 Docker CE (社区版)
现在,你可以安装 Docker 了:
sudo apt install docker-ce
1.7 启动 Docker 服务
安装完成后,启动 Docker 服务:
sudo systemctl start docker
1.8 设置 Docker 开机启动
为了在系统启动时自动启动 Docker,可以使用以下命令:
sudo systemctl enable docker
1.9 验证 Docker 是否安装成功
你可以通过运行以下命令来验证 Docker 是否安装成功:
sudo docker --version
如果安装成功,你将看到 Docker 的版本信息。
1.10 配置非 root 用户运行 Docker (可选)
如果你不想每次使用 Docker 命令时都输入 sudo
,可以将你的用户添加到 docker
组:
sudo usermod -aG docker $USER
然后,退出当前会话并重新登录,或者执行以下命令来刷新用户组设置:
newgrp docker
这样,你就可以不使用 sudo
来运行 Docker 了。
1.11 测试 Docker
你可以运行一个简单的 Docker 容器来验证是否一切正常:
docker run hello-world
这会从 Docker Hub 下载并运行一个测试容器,输出欢迎消息,说明 Docker 安装成功。
完成这些步骤后,Docker 就安装并配置好在你的 Ubuntu 20.04 系统上运行了。
2. 安装Docker Compose
在 Ubuntu 20.04 上安装 Docker Compose 的步骤如下:
2.1 安装 Docker Compose
- 下载最新版本的 Docker Compose:
首先,下载 Docker Compose 的最新稳定版本。可以从 GitHub 获取最新版本号。执行以下命令以下载 Docker Compose:
sudo curl -L "https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | jq -r .tag_name)/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
在这条命令中,$(curl -s https://api.github.com/repos/docker/compose/releases/latest | jq -r .tag_name)
会动态获取最新的 Docker Compose 版本号。
- 设置可执行权限:
下载完成后,你需要将 Docker Compose 设置为可执行文件:
sudo chmod +x /usr/local/bin/docker-compose
- 验证 Docker Compose 安装:
安装完成后,运行以下命令来验证是否成功安装:
docker-compose --version
你应该看到类似如下的输出,表示安装成功:
docker-compose version 1.29.2, build 5becea4c
2.2 使用 Docker Compose
安装完成后,你可以使用 Docker Compose 来定义和运行多容器 Docker 应用。
例如,创建一个 docker-compose.yml
文件来定义服务,并使用以下命令启动它们:
docker-compose up
2.3 升级 Docker Compose(可选)
如果你已经安装了 Docker Compose,并希望将其升级到最新版本,可以使用以下命令:
sudo curl -L "https://github.com/docker/compose/releases/download/$(curl -s https://api.github.com/repos/docker/compose/releases/latest | jq -r .tag_name)/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
2.4 卸载 Docker Compose(可选)
如果你需要卸载 Docker Compose,只需要删除可执行文件:
sudo rm /usr/local/bin/docker-compose
这样就完成了在 Ubuntu 20.04 上安装和配置 Docker Compose 的过程。
3. 创建Cobalt项目目录
mkdir cobalt
4. 进入目录添加docker-compose.yml配置文件
进入cobalt目录
cd cobalt
添加配置文件,执行如下命令进入编辑模式
sudo vim docker-compose.yml
拷贝如下内容,替换API_URL参数为自己的二级域名,如果cookies.json文件还没配置,就先注释掉
COOKIE_PATH: "/cookies.json"
和
volumes:
- ./cookies.json:/cookies.json
Ctrl+V 粘贴,之后按ESC,输入 :wq 保存退出。
services:
cobalt-api:
image: ghcr.io/imputnet/cobalt:10
init: true
read_only: true
restart: unless-stopped
container_name: cobalt-api
ports:
#- 9000:9000/tcp
# if you use a reverse proxy (such as nginx),
# uncomment the next line and remove the one above (9000:9000/tcp):
- 127.0.0.1:9000:9000
environment:
# replace https://api.url.example/ with your instance's url
# or else tunneling functionality won't work properly
API_URL: "https://api.XXX.com/"
# if you want to use cookies for fetching data from services,
# uncomment the next line & volumes section
COOKIE_PATH: "/cookies.json"
# it's recommended to configure bot protection or api keys if the instance is public,
# see /docs/protect-an-instance.md for more info
# see /docs/run-an-instance.md for more variables that you can use here
labels:
- com.centurylinklabs.watchtower.scope=cobalt
# uncomment only if you use the COOKIE_PATH variable
volumes:
- ./cookies.json:/cookies.json
# watchtower updates the cobalt image automatically
watchtower:
image: ghcr.io/containrrr/watchtower
restart: unless-stopped
command: --cleanup --scope cobalt --interval 900 --include-restarting
volumes:
- /var/run/docker.sock:/var/run/docker.sock
cookies.json文件主要是配置Youtube的Token参数。如果不需要支持Youtube平台的转换和下载可以不配置。
如果还没配置HTTPS的环境,可以先注释掉- 127.0.0.1:9000:9000,恢复- 9000:9000/tcp,等配置nginx代理之后再恢复回来。
5. 启动Cobalt项目容器
docker compose up -d
三、配置HTTPS代理
1. 安装 Certbot
Certbot 是用于获取和管理 SSL 证书的工具,您可以通过以下命令安装(Ubuntu/Debian环境):
sudo apt update
sudo apt install certbot python3-certbot-nginx
2. 获取 SSL 证书
使用 Certbot 为您的域名获取 SSL 证书,yourdomain
替换为自己的域名:
sudo certbot --nginx -d api.yourdomain.com
这将自动为您配置 Nginx 以支持 HTTPS,并获取 Let’s Encrypt 提供的 SSL 证书。Certbot 会提示您输入电子邮件地址以及是否同意服务条款。
3. 配置自动续期
Certbot 会自动配置证书续期,但您可以手动运行以下命令以测试续期:
sudo certbot renew --dry-run
4. 检查 Nginx 配置
Certbot 会自动更新 Nginx 配置,您可以检查 /etc/nginx/sites-available/api.yourdomain.com
是否包含类似以下内容的配置:
server {
listen 80;
server_name api.yourdomain.com;
# Redirect all HTTP requests to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name api.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:9000; # 替换为 Cobalt 使用的端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
5. 重新加载 Nginx
完成配置后,重新加载 Nginx 以使更改生效:
sudo systemctl reload nginx
6. 测试 HTTPS
上面都配置好之后,恢复- 127.0.0.1:9000:9000的配置,注释掉- 9000:9000/tcp,执行下面两条命令,重启下Docker:
docker-compose down
docker-compose up -d
在浏览器中访问 https://api.yourdomain.com
,确认 HTTPS 是否可以正常访问。
通过这些步骤,您就可以为 api.yourdomain.com
配置 HTTPS,使其安全访问。
四、配置Youtube Token
1. 先clone项目到本地电脑
git clone https://github.com/imputnet/cobalt.git
2. 进入项目目录,安装下环境配置
cd cobalt/api
pnpm install
3. 打开Chrome无痕浏览模式,避免账号关联
打开 https://www.google.com/device 地址
用你专门申请的Google账号登录(比如使用网易邮箱申请一个Google Gmail账号),账号激活如果需要美区电话号码认证,可以使用接码平台(https://sms-activate.guru/)购买一个十几分钟使用期限的美区电话号码。
从Cobalt项目的issue信息来看,当账号调用Youtube接口次数比较大的时候,账号容易被封,所以为了避免账号损失,最好不要使用私人账号,额外申请一个或多个账号用于这个项目的使用。
4. 执行生成Token命令
pnpm -C api token:youtube
把控制台输出的类似如下的信息拷贝出来:
"access_token=xxxxxxx; refresh_token=xxxxxxx; scope=https://www.googleapis.com/auth/youtube-paid-content https://www.googleapis.com/auth/youtube; token_type=Bearer; expiry_date=2024-11-11T02:19:43.303Z"
配置到cookies.json文件,配置示例如下:
{
"youtube_oauth": [
"access_token=xxxxxxx; refresh_token=xxxxxxx; scope=https://www.googleapis.com/auth/youtube-paid-content https://www.googleapis.com/auth/youtube; token_type=Bearer; expiry_date=2024-11-11T02:19:43.303Z"
]
}
如果有多个Token可以用英文字符逗号隔开,之后打开docker-compose.yml配置文件里面关于cookies.json的两个配置,重启下Docker实例就可以立即生效。
Token的有效期是一天,Cobalt会自动申请更新Token,在第一次配置完成之后就无需关注,除非账号被封需要重新执行下以上步骤。
最后这个步骤是最难搞的,个人测试,即使开了“科学上网”,打开了系统全局代理,也没法访问Youtube的API域名地址,ping这个地址直接出现超时异常。后面谷歌搜索了其他生成Youtube Token的方法,虽然可以生成Token,但是不能用在这个项目的配置上。最后只好找在美国的大学同学帮操作了下,顺利生成了Token,同学说可以搞个Mac Mini,直接把路由配置成“科学上网”的方式,未做测试,这个不知道是否可以行。
除了上面这些,也可以增加下保护实例的配置:https://github.com/imputnet/cobalt/blob/main/docs/protect-an-instance.md
五、刷新Token的JS脚本
如果需要使用其他方式获取Token,可以参考以下这两篇文章,这边的方式获取的Token不能用在Cobalt项目上:
Retrieve YouTube API v3 key with Node.js
结合下面的JS脚本来获取和刷新cookies.json的Token内容。
var fs = require('fs');
var readline = require('readline');
var { google } = require('googleapis');
var OAuth2 = google.auth.OAuth2;
var TOKEN_PATH = './cookies.json';
// Load client secrets from a local file (client_secret.json).
fs.readFile('client_secret.json', function processClientSecrets(err, content) {
if (err) {
console.log('Error loading client secret file:', err);
return;
}
// Authorize a client with the loaded credentials, then call the YouTube API.
authorize(JSON.parse(content), getNewTokenAndUpdateFile);
});
/**
* Create an OAuth2 client with the given credentials, and then execute the
* given callback function.
*
* @param {Object} credentials The authorization client credentials.
* @param {function} callback The callback to call with the authorized client.
*/
function authorize(credentials, callback) {
var clientSecret = credentials.web.client_secret;
var clientId = credentials.web.client_id;
var redirectUrl = credentials.web.redirect_uris[0];
var oauth2Client = new OAuth2(clientId, clientSecret, redirectUrl);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, function (err, tokenData) {
if (err) {
getNewToken(oauth2Client, callback);
} else {
var token = JSON.parse(tokenData).youtube_oauth[0];
oauth2Client.credentials = JSON.parse(token);
callback(oauth2Client);
}
});
}
/**
* Get and store new token after prompting for user authorization.
*
* @param {google.auth.OAuth2} oauth2Client The OAuth2 client to get token for.
* @param {function} callback The callback to call with the authorized client.
*/
function getNewToken(oauth2Client, callback) {
var authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: ['https://www.googleapis.com/auth/youtube.readonly'],
prompt: 'consent' // Ensures that a refresh token is returned
});
console.log('Authorize this app by visiting this url:', authUrl);
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Enter the code from that page here: ', function (code) {
rl.close();
oauth2Client.getToken(code, function (err, token) {
if (err) {
console.log('Error while trying to retrieve access token', err);
return;
}
oauth2Client.credentials = token;
storeToken(token);
callback(oauth2Client);
});
});
}
/**
* Store the token in the cookies.json file under the youtube_oauth field.
*
* @param {Object} token The token to store.
*/
function storeToken(token) {
fs.readFile(TOKEN_PATH, (err, data) => {
var updatedData = { youtube_oauth: [] };
if (!err) {
try {
updatedData = JSON.parse(data);
} catch (e) {
console.error('Error parsing cookies.json:', e);
}
}
// Replace the youtube_oauth field with the new token.
updatedData.youtube_oauth = [JSON.stringify(token)];
fs.writeFile(TOKEN_PATH, JSON.stringify(updatedData, null, 2), (err) => {
if (err) {
console.error('Error writing token to file:', err);
} else {
console.log('Token stored to', TOKEN_PATH);
}
});
});
}
/**
* Refreshes the access token and updates the cookies.json file.
*
* @param {google.auth.OAuth2} oauth2Client The OAuth2 client.
*/
function getNewTokenAndUpdateFile(oauth2Client) {
oauth2Client.refreshAccessToken((err, tokens) => {
if (err) {
console.error('Error refreshing access token:', err);
return;
}
console.log('New access token obtained:', tokens.access_token);
oauth2Client.credentials = tokens;
storeToken(tokens);
});
}
在 VPS 服务器上,你可以使用 cron
作业来配置定时任务,以每 55 分钟执行一次 generateNewToken.js
脚本来获取新的 Token。以下是具体步骤:
1. 检查 Node.js 可执行路径
确保在 cron
中可以正确调用 node
。运行以下命令获取 Node.js 的可执行路径:
which node
通常输出类似 /usr/bin/node
或 /usr/local/bin/node
。这个路径将在 cron
作业中使用。
2. 使用 pwd
命令查看当前路径
如果你在终端中处于 generateNewToken.js
文件所在的文件夹中,运行以下命令可以查看当前路径:
pwd
3. 编辑 crontab
文件
使用以下命令编辑 crontab
文件:
crontab -e
4. 添加 cron
作业
在 crontab
文件中,添加以下行,每 55 分钟运行一次 generateNewToken.js
脚本。将 <path-to-your-script>
替换为第2步中获取的 generateNewToken.js
文件的绝对路径,<path-to-node>
替换为第 1 步中获取的 Node.js 路径。
*/55 * * * * <path-to-node> <path-to-your-script>/generateNewToken.js >> <path-to-your-script>/generateNewToken.log 2>&1
解释
*/55 * * * *
:每 55 分钟运行一次任务。<path-to-node>
:Node.js 的绝对路径。<path-to-your-script>/generateNewToken.js
:脚本的绝对路径。>> <path-to-your-script>/generateNewToken.log 2>&1
:将输出和错误日志重定向到generateNewToken.log
文件。
5. 保存和退出 crontab
编辑完成后,保存并退出编辑器。cron
将自动加载和应用新的配置。
6. 检查 cron
作业是否已配置
运行以下命令,验证 cron
作业已成功添加:
crontab -l
7. 查看日志文件(可选)
检查 generateNewToken.log
文件,确保任务按预期运行,并调试任何潜在的问题:
tail -f <path-to-your-script>/generateNewToken.log
补充建议
- 权限:确保
generateNewToken.js
文件具有可执行权限,可以使用chmod +x generateNewToken.js
赋予权限。 - 环境变量:如果
generateNewToken.js
依赖特定的环境变量,确保cron
作业的环境中设置了这些变量,或在脚本中加载.env
文件。
通过上述步骤,你可以在 VPS 上配置一个定时任务,每 55 分钟自动运行 generateNewToken.js
脚本,以获取新的 YouTube API 访问令牌。
扩展阅读:
微信公众号
转载请注明出处:陈文管的博客 – 在线视频转音频后端服务搭建
发表回复