Java 实现通过 YouTube 链接下载视频并上传阿里云 OSS

653 阅读2分钟

参考 github 项目

github.com/yt-dlp/yt-d…

服务所在机器下载 yt-dlp

  • 下载 yt-dlp 可执行文件
sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp
  • 添加执行权限
sudo chmod a+rx /usr/local/bin/yt-dlp
  • 验证安装是否成功
yt-dlp --version

在这里插入图片描述

相关代码

package cn.xxx.aimperson.biz.manager;

import cn.xxx.ms.core.base.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.UUID;

@Slf4j
@Component
public class YouTubeManager {

    @Resource
    OSSManager ossManager;

    /**
     * 从YouTube下载音频并上传到阿里云OSS
     *
     * 注意使用该功能需要先安装 yt-dlp
     * 下载 yt-dlp 可执行文件:
     *      sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp
     * <p>
     * 添加执行权限:
     *      sudo chmod a+rx /usr/local/bin/yt-dlp
     * <p>
     * 验证安装:
     *      yt-dlp --version
     *
     * @param youtubeUrl YouTube视频的URL
     * @return 音频文件在OSS上的URL
     */
    public String downloadAudioToOss(String youtubeUrl) {
        log.info("入参 youtubeUrl : {}", youtubeUrl);
        String fileUrl = null;

        // 生成唯一的对象名称,用于在OSS上保存音频文件
        String objectName = "aimperson/av/" + DateUtil.getNowYMDH() + "/" + UUID.randomUUID().toString() + ".mp3";

        // 使用yt-dlp工具下载音频
        ProcessBuilder processBuilder = new ProcessBuilder(
                "yt-dlp", "-f", "bestaudio", "--extract-audio", "--audio-format", "mp3", "-o", "-", youtubeUrl
        );
        Process process = null;
        try {
            process = processBuilder.start();
        } catch (Exception e) {
            // 记录启动进程失败的日志
            log.error("获取管道失败 ", e);
        }

        // 从进程的输入流中读取下载的音频数据,并上传到OSS
        try (InputStream inputStream = process.getInputStream()) {
            fileUrl = uploadInputStreamLocalRStr(objectName, inputStream);
        } catch (Exception e) {
            // 记录上传到OSS失败的日志
            log.error("上传阿里云OSS失败 ", e);
        } finally {
            // 关闭进程
            if (process != null) {
                process.destroy();
            }
        }
        // 记录输出参数
        log.info("出参 fileUrl : {}", fileUrl);
        return fileUrl;
    }

	/**
     * 上传输入流到内容读入内存,创建一个可重置的ByteArrayInputStream,再上传阿里云 OSS
     * 注意:这解决了输入流可能不支持重置的问题
     *
     * @param objectName  对象在存储系统中的名称
     * @param inputStream 要上传的输入流
     * @return 上传成功后资源的URL
     */
    public String uploadInputStreamLocalRStr(String objectName, InputStream inputStream) {
        // 初始化内容字节数组为空
        byte[] content = new byte[0];
        String url = null;
        try {
            // 将输入流内容读取到字节数组
            content = IOUtils.toByteArray(inputStream);
            log.info("流大小 : {} byte", content.length);
            // 创建一个ByteArrayInputStream以供上传使用
            InputStream bufferedInputStream = new ByteArrayInputStream(content);

            // 使用OSS客户端将内容上传到指定的存储桶和对象名称
            ossClient.putObject(bucket, objectName, bufferedInputStream);
            // 构建资源的URL
            url = CdnUtil.getDomain(CdnEnum.resCdn) + "/" + objectName;
        } catch (IOException e) {
            log.error("失败 ", e);
        }
        log.info("出参 objectName : {} url : {}", objectName, url);
        return url;
    }

}