腾讯云视频点播

这篇具有很好参考价值的文章主要介绍了腾讯云视频点播。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  视频点播我去年写过一篇阿里云的,这次写腾讯云。

1、腾讯云点播介绍

  腾讯云点播(Video on Demand,VOD)基于腾讯多年技术积累与基础设施建设,为有音视频应用相关需求的客户提供包括音视频存储管理、音视频转码处理、音视频加速播放和音视频通信服务的一站式解决方案。

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

  文档中心:https://cloud.tencent.com/document/product/266

1.1 开通“云点播”服务

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

1.2 管理控制台

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

1.3 上传视频

上传视频可将视频上传到云点播的存储中,以进行后续的处理和分发等。

  • 单击左侧菜单栏【媒资管理 > 视频管理】,默认展示【已上传】标签页;
  • 点击【上传视频】按钮;
  • 单击【选择视频】,选择本地视频文件;
  • 单击【开始上传】;
  • 页面将自动跳转至【正在上传】标签页, 本地文件所在行【状态】栏为“上传成功”时,单击【已上传】标签页,可见完成上传的视频;

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

1.4 前端集成

  前端集成有两种方式,使用“超级播放器预览”与“web播放器预览”,后者代码已经不更新,推荐使用前者,因此“web播放器预览”仅做了解。

  1、查看“web播放器预览”;

  说明:需要将视频进行转码,才能支持超级播放器播放,转码为:自适应码流

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

  2、查看任务流设置

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

  3、查看详情

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

  当前任务流就是系统默认的“自适应码流”任务流

  4、在【音视频管理】重新上传视频

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

  5、查看详情

  6、复制代码index.html到项目,即可播放

2、后端视频点播接口(集成Java SDK)

2.1 创建相关类

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

2.2 引入相关依赖

<dependency>
    <groupId>com.qcloud</groupId>
    <artifactId>vod_api</artifactId>
    <version>2.1.4</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2.3 编写Controller

  (1)上传视频集成方案:https://cloud.tencent.com/document/product/266/10276

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

(2)删除视频

  地址:https://console.cloud.tencent.com/api/explorer?Product=vod&Version=2018-07-17&Action=DescribeMediaInfos&SignVersion=

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

@Api(tags = "腾讯云点播")
@RestController
@RequestMapping("/admin/vod")
public class VodController {

    @Autowired
    private VodService vodService;

    //返回客户端上传视频的签名
    @GetMapping("sign")
    public Result sign(){
        Signature sign = new Signature();
        // 设置 App 的云 API 密钥
        sign.setSecretId(ConstantPropertiesUtil.ACCESS_KEY_ID);
        sign.setSecretKey(ConstantPropertiesUtil.ACCESS_KEY_SECRET);
        sign.setCurrentTime(System.currentTimeMillis() / 1000);
        sign.setRandom(new Random().nextInt(java.lang.Integer.MAX_VALUE));
        sign.setSignValidDuration(3600 * 24 * 2); // 签名有效期:2天
        try {
            String signature = sign.getUploadSignature();
            System.out.println("signature : " + signature);
            return Result.ok(signature);
        } catch (Exception e) {
            System.out.print("获取签名失败");
            e.printStackTrace();
            throw  new GgktException(20001,"获取签名失败");
        }
    }

    //上传视频接口
    @ApiOperation("上传视频接口")
    @PostMapping("upload")
    public Result upload(){
        String fileId=vodService.uploadVideo();
        return Result.ok(fileId);
    }

    //删除腾讯云视频
    @ApiOperation("删除腾讯云视频")
    @DeleteMapping("remove/{fileId}")
    public Result remove(@PathVariable String fileId){
        vodService.removeVideo(fileId);
        return Result.ok(null);
    }

}

2.4 编写Service

(1)VodService定义方法

public interface VodService {
    //上传视频接口
    String uploadVideo();

    //删除腾讯云视频
    void removeVideo(String fileId);
}

(2)VodServiceImpl实现方法

@Service
public class VodServiceImpl implements VodService {
    //上传视频接口
    @Override
    public String uploadVideo() {
        //指定当前腾讯云账号的id和key
        VodUploadClient client = new VodUploadClient(ConstantPropertiesUtil.ACCESS_KEY_ID,
                ConstantPropertiesUtil.ACCESS_KEY_SECRET);
        //上传请求对象
        VodUploadRequest request = new VodUploadRequest();
        //设置上传的视频文件在本地路径
        request.setMediaFilePath("I:\\temp\\faster.mp4");
        //任务流
        request.setProcedure("LongVideoPreset");
        try {
            //调用方法上传视频,指定地域
            VodUploadResponse response = client.upload("ap-guangzhou", request);
            //获取上传之后的视频id
            String fileId = response.getFileId();
            return fileId;
        } catch (Exception e) {
            // 业务方进行异常处理
            throw new GgktException(20001,"上传视频失败");
        }
    }

    //删除腾讯云视频
    @Override
    public void removeVideo(String fileId) {
        try{
            // 实例化一个认证对象,入参需要传入腾讯云账户secretId,secretKey,此处还需注意密钥对的保密
            // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
            Credential cred = new Credential(ConstantPropertiesUtil.ACCESS_KEY_ID,
                    ConstantPropertiesUtil.ACCESS_KEY_SECRET);
            // 实例化一个http选项,可选的,没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("vod.tencentcloudapi.com");
            // 实例化一个client选项,可选的,没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            VodClient client = new VodClient(cred, "", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            DeleteMediaRequest req = new DeleteMediaRequest();
            req.setFileId(fileId);
            // 返回的resp是一个DeleteMediaResponse的实例,与请求对象对应
            DeleteMediaResponse resp = client.DeleteMedia(req);
            // 输出json格式的字符串回包
            System.out.println(DeleteMediaResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
            throw new GgktException(20001,"删除视频失败");
        }
    }
}

   这里暂时路径写死上传的,因为我在文档中并没有找到有关文件流上传方式的API。

  不过腾讯云提供了客户端上传的方式,不用服务端上传也是可以的。

3、另一种上传方式:客户端上传

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

3.1 操作步骤一(申请上传签名)

(1)找到Java签名示例

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

(2)VodController编写签名接口

Signature类

import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Encoder;
public class Signature {
    private String secretId;
    private String secretKey;
    private long currentTime;
    private int random;
    private int signValidDuration;
    private static final String HMAC_ALGORITHM = "HmacSHA1"; //签名算法
    private static final String CONTENT_CHARSET = "UTF-8";
    public static byte[] byteMerger(byte[] byte1, byte[] byte2) {
        byte[] byte3 = new byte[byte1.length + byte2.length];
        System.arraycopy(byte1, 0, byte3, 0, byte1.length);
        System.arraycopy(byte2, 0, byte3, byte1.length, byte2.length);
        return byte3;
    }
    // 获取签名
    public String getUploadSignature() throws Exception {
        String strSign = "";
        String contextStr = "";
        // 生成原始参数字符串
        long endTime = (currentTime + signValidDuration);
        contextStr += "secretId=" + java.net.URLEncoder.encode(secretId, "utf8");
        contextStr += "&currentTimeStamp=" + currentTime;
        contextStr += "&expireTime=" + endTime;
        contextStr += "&random=" + random;
        //设置任务流
        contextStr+="&procedure=LongVideoPreset";
        try {
            Mac mac = Mac.getInstance(HMAC_ALGORITHM);
            SecretKeySpec secretKey = new SecretKeySpec(this.secretKey.getBytes(CONTENT_CHARSET), mac.getAlgorithm());
            mac.init(secretKey);
            byte[] hash = mac.doFinal(contextStr.getBytes(CONTENT_CHARSET));
            byte[] sigBuf = byteMerger(hash, contextStr.getBytes("utf8"));
            strSign = base64Encode(sigBuf);
            strSign = strSign.replace(" ", "").replace("\n", "").replace("\r", "");
        } catch (Exception e) {
            throw e;
        }
        return strSign;
    }
    private String base64Encode(byte[] buffer) {
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(buffer);
    }
    public void setSecretId(String secretId) {
        this.secretId = secretId;
    }
    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }
    public void setCurrentTime(long currentTime) {
        this.currentTime = currentTime;
    }
    public void setRandom(int random) {
        this.random = random;
    }
    public void setSignValidDuration(int signValidDuration) {
        this.signValidDuration = signValidDuration;
    }
}

VodController类

 //返回客户端上传视频的签名
    @GetMapping("sign")
    public Result sign(){
        Signature sign = new Signature();
        // 设置 App 的云 API 密钥
        sign.setSecretId(ConstantPropertiesUtil.ACCESS_KEY_ID);
        sign.setSecretKey(ConstantPropertiesUtil.ACCESS_KEY_SECRET);
        sign.setCurrentTime(System.currentTimeMillis() / 1000);
        sign.setRandom(new Random().nextInt(java.lang.Integer.MAX_VALUE));
        sign.setSignValidDuration(3600 * 24 * 2); // 签名有效期:2try {
            String signature = sign.getUploadSignature();
            System.out.println("signature : " + signature);
            return Result.ok(signature);
        } catch (Exception e) {
            System.out.print("获取签名失败");
            e.printStackTrace();
            throw  new GgktException(20001,"获取签名失败");
        }
    }

3.2 操作步骤二(SDK上传)

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

3.3 下载Demo源码修改

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

3.3.1 html测试文件上传

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>QCloud VIDEO UGC UPLOAD SDK</title>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
  <style type="text/css">
    .text-danger {
      color: red;
    }

    .control-label {
      text-align: left !important;
    }

    #resultBox {
      width: 100%;
      height: 300px;
      border: 1px solid #888;
      padding: 5px;
      overflow: auto;
      margin-bottom: 20px;
    }

    .uploaderMsgBox {
      width: 100%;
      border-bottom: 1px solid #888;
    }

    .cancel-upload {
      text-decoration: none;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <div id="content">
    <div class="container">
      <h1>UGC-Uploader</h1>
    </div>
  </div>
  <div class="container" id="main-area">
    <div class="row" style="padding:10px;">
      <p>
        示例1点击“直接上传视频”按钮即可上传视频。<br></p>
    </div>
    <form ref="vExample">
      <input type="file" style="display:none;" ref="vExampleFile" @change="vExampleUpload" />
    </form>
    <div class="row" style="padding:10px;">
      <h4>示例1:直接上传视频</h4>
      <a href="javascript:void(0);" class="btn btn-default" @click="vExampleAdd">直接上传视频</a>
    </div>
      <!-- 上传信息组件	 -->
      <div class="uploaderMsgBox" v-for="uploaderInfo in uploaderInfos">
        <div v-if="uploaderInfo.videoInfo">
          视频名称:{{uploaderInfo.videoInfo.name + '.' + uploaderInfo.videoInfo.type}};
          上传进度:{{Math.floor(uploaderInfo.progress * 100) + '%'}};
          fileId:{{uploaderInfo.fileId}};
          上传结果:{{uploaderInfo.isVideoUploadCancel ? '已取消' : uploaderInfo.isVideoUploadSuccess ? '上传成功' : '上传中'}};
          <br>
          地址:{{uploaderInfo.videoUrl}};
          <a href="javascript:void(0);" class="cancel-upload" v-if="!uploaderInfo.isVideoUploadSuccess && !uploaderInfo.isVideoUploadCancel" @click="uploaderInfo.cancel()">取消上传</a><br>
        </div>
        <div v-if="uploaderInfo.coverInfo">
          封面名称:{{uploaderInfo.coverInfo.name}};
          上传进度:{{Math.floor(uploaderInfo.coverProgress * 100) + '%'}};
          上传结果:{{uploaderInfo.isCoverUploadSuccess ? '上传成功' : '上传中'}};
          <br>
          地址:{{uploaderInfo.coverUrl}};
          <br>
        </div>
      </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.21/vue.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
  <script src="https://cdn-go.cn/cdn/vod-js-sdk-v6/latest/vod-js-sdk-v6.js"></script>

  <script type="text/javascript">

    ;(function () {

      /**
       * 计算签名。调用签名接口获取
      **/
      function getSignature() {
        return axios.get("http://localhost:8333/admin/vod/sign").then(response =>{
          return response.data.data
        })
      };
      var app = new Vue({
        el: '#main-area',
        data: {
          uploaderInfos: [],

          vcExampleVideoName: '',
          vcExampleCoverName: '',

          cExampleFileId: '',
        },
        created: function () {
          this.tcVod = new TcVod.default({
            getSignature: getSignature
          })
        },
        methods: {
          /**
           * vExample示例。添加视频
          **/
          vExampleAdd: function () {
            this.$refs.vExampleFile.click()
          },
          /**
           * vExample示例。上传视频过程。
          **/
          vExampleUpload: function () {
            var self = this;
            var mediaFile = this.$refs.vExampleFile.files[0]

            var uploader = this.tcVod.upload({
              mediaFile: mediaFile,
            })
            uploader.on('media_progress', function (info) {
              uploaderInfo.progress = info.percent;
            })
            uploader.on('media_upload', function (info) {
              uploaderInfo.isVideoUploadSuccess = true;
            })

            console.log(uploader, 'uploader')

            var uploaderInfo = {
              videoInfo: uploader.videoInfo,
              isVideoUploadSuccess: false,
              isVideoUploadCancel: false,
              progress: 0,
              fileId: '',
              videoUrl: '',
              cancel: function() {
                uploaderInfo.isVideoUploadCancel = true;
                uploader.cancel()
              },
            }

            this.uploaderInfos.push(uploaderInfo)
            uploader.done().then(function(doneResult) {
              console.log('doneResult', doneResult)
              uploaderInfo.fileId = doneResult.fileId;
              return doneResult.video.url;
            }).then(function (videoUrl) {
              uploaderInfo.videoUrl = videoUrl
              self.$refs.vExample.reset();
            })
          },
          // cExample 上传过程
          cExampleUpload: function() {
            var self = this;
            var coverFile = this.$refs.cExampleCover.files[0];

            var uploader = this.tcVod.upload({
              fileId: this.cExampleFileId,
              coverFile: coverFile,
            })
            uploader.on('cover_progress', function(info) {
              uploaderInfo.coverProgress = info.percent;
            })
            uploader.on('cover_upload', function(info) {
              uploaderInfo.isCoverUploadSuccess = true;
            })
            console.log(uploader, 'uploader')

            var uploaderInfo = {
              coverInfo: uploader.coverInfo,
              isCoverUploadSuccess: false,
              coverProgress: 0,
              coverUrl: '',
              cancel: function () {
                uploader.cancel()
              },
            }

            this.uploaderInfos.push(uploaderInfo)

            uploader.done().then(function (doneResult) {
              console.log('doneResult', doneResult)
              uploaderInfo.coverUrl = doneResult.cover.url;
              self.$refs.cExample.reset();
            })
          },
        },
      })
    })();

  </script>
  <!-- Global site tag (gtag.js) - Google Analytics -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=UA-26476625-7"></script>
  <script>
    // add by alsotang@gmail.com
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
    gtag('config', 'UA-26476625-7');
  </script>
</body>
</html>

  改下代码中的这里,请求签名接口。

  本来应该访问8301端口,但是我用Spring Cloud Gateway配置了网关,nacos配置了服务注册,所以这里就将请求交给网关,由网关负责转发。

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

  运行这个html测试下:

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

  点击上传视频按钮,选择视频

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

腾讯云点播和阿里云点播,阿里云,腾讯云,云计算,视频点播,音视频

  功能基本实现了。文章来源地址https://www.toymoban.com/news/detail-712529.html

到了这里,关于腾讯云视频点播的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot + vue 整合 阿里云 视频点播 功能

    1.1、找到视频点播 1.2、进入管理控制台 1.2、开通服务 1.3、选择“按使用流量计费”,开通服务 1.4、开通后,进入管理控制台 1.5、上传音 / 视频 1.6、启用存储地址 1.7、已启用 1.8、选择上传的音频,开始上传 1.9、上传成功 1.10、分类管理 1.11、视频转码 1.12、再上传一个视频

    2024年02月02日
    浏览(33)
  • 腾讯云-云点播:设置视频录制的回调函数,将腾讯录制的音频文件保存到本地中

    使用场景: 我们在使用腾讯的云点播实现视频的录制功能时,需要将录制的视频保存到本地系统中时。 1、下载腾讯录制的视频文件 2、删除腾讯点播录制的视频 3、设置回调函数 回调时,腾讯响应的数据格式 {             \\\'EventGroupId\\\': 3,             \\\'EventType\\\': 311,

    2024年02月13日
    浏览(34)
  • 小程序中无法播放阿里云的视频点播

    视频直接存在自己的服务器,视频大了会存在卡顿现象,只能用阿里云或其它服务商的相关服务。 原来在APP中已有了视频播放的功能,而且已经能正常使用,但视频的url是 http。 现在期望在小程序中也添加视频播放的功能。 申请相关url的ssl证书, 进阿里云了搜索 ssl证书,进

    2024年02月06日
    浏览(50)
  • Spring Boot集成阿里云视频点播服务的过程记录

    在对接阿里云视频点播服务时,踩了不少的坑。特此记录阿里云视频点播服务的相关使用。 同时使用Spring Boot集成阿里云视频点播服务,对接其上传SDK、服务端SDK、播放器SDK,最终完成如下Demo演示。 视频点播(ApsaraVideo VoD,简称VoD)是集视频采集、编辑、上传、媒体资源管

    2023年04月21日
    浏览(36)
  • 谷粒学苑项目实战(十四):实现阿里云视频点播功能(java编码实现)

            视频点播(ApsaraVideo for VoD)是集音视频采集、编辑、上传、自动化转码处理、媒体资源管理、分发加速于一体的一站式音视频点播解决方案。          在阿里云产品中找到视频点播,开通。         选择按流量计费(小视频大概也就话几毛钱)         点击开

    2023年04月25日
    浏览(60)
  • 通过阿里云函数计算FC实现音视频转码

    1.进入阿里云函数计算FC页面 2.创建音视频转码应用         可以看到代码,看到相关的传参   3.进行测试   编辑测试参数,使用账号的OSS中的资源    点击测试函数进行测试 可以在OSS中看到生成的mp4格式的视频了   测试后发现函数计算可以使用 4. 接下来就是在项目中通过

    2024年02月11日
    浏览(52)
  • 计算机团队毕业设计:JAVA在线教育视频点播学习系统+微信小程序系统设计与实现

    本次选用JAVA进行在线教育视频学习点播系统团队毕业设计开发,包含:WEB网站系统+微信小程序系统。 开发操作系统:windows10 + 8G内存 + 500G WEB开发环境:JDK1.8 + Tomcat8 WEB开发语言:Java WEB开发框架:springboot WEB模板引擎:Thymeleaf WEB常规技术:html + css +javascript WEB开发工具:Id

    2024年02月13日
    浏览(51)
  • CRMEB知识付费二次开发 加密阿里云视频MP4点播链接为m3u8格式 hls blob协议

    只有添加分发加速的域名才能使用HLS加密,同时也要做HTTPS证书添加,不然也会报错。 1、这是电脑端视频播放页面效果 2、这个手机端H5视频播放页面效果 3、在网站后台上传你的视频内容 4、上传完之后可以进行预览 5、在阿里云控制台设置就好自己的转码模板 将不转码设为

    2024年02月08日
    浏览(54)
  • uniapp对接腾讯云IM+音视频。音视频含UI集成

    提示:作者已经实现uniapp集成腾讯云IM+音视频到android和ios平台,如有疑问可在下方留言。音视频为含ui集成 uniapp腾讯云音视频插件地址 官方插件显示的ios版本为9-15,本人ios版本号为16.1,亲测可行 uniapp 腾讯云音视频文档 uniapp 腾讯云IM文档 注意这个是uni的v3+ts版本,如果是v2版

    2024年02月07日
    浏览(47)
  • 浅述HLS视频服务器EasyDarwin视频直播点播平台如何快速搭建一个视频点播系统

    EasyDarwin视频直播点播平台能实现视频流媒体的上传、转码、存储、录像、推拉流、直播、点播等功能,可兼容Windows、Android、iOS、Mac等操作系统,系统支持HTTP、HLS、RTMP等播出协议,具备较强的可拓展性与灵活性。 EasyDarwin的特点包括: 1.开源免费:EasyDarwin以开源的形式发布

    2024年02月20日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包