nginx + rtmp 搭建流媒体服务器直播平台

用nginx实现一个直播服务—RTMP推流和HTTP-FLV拉流 这篇文章主要记录用nginx实现直播服务,通过RTMP推流和通过HTTP-FLV或RTMP拉流,并在页面中播放。 阅读详情

一、安装与配置nginx服务器

安装nginx:

1,安装参考播客:https://blog.youkuaiyun.com/u012946310/article/details/81535751

2,安装完成后下载 nginx-rtmp-module 模块(我这里的目录是在/usr/local/nginx-1.15.0 下面)

cd /usr/local/nginx-1.15.0/

nginx-rtmp-module 的官方 github 下载地址:https://github.com/arut/nginx-rtmp-module
这里使用git进行下载:

git clone https://github.com/arut/nginx-rtmp-module.git 

( 如果没有安装git使用yun进行安装,yum install git)

3,重新编译 nginx,添加 nginx-rtmp-module 模块

./configure --prefix=/usr/local/nginx  --add-module=nginx-rtmp-module  --with-http_ssl_module
make
make install

4,nginx 与 nginx-rtmp-module 模块安装完成,修改 nginx.conf 配置文件

#在最外层增加如下配置
rtmp {
    server {
        listen 1935; #监听的端口
        chunk_size 4000;

        #rtmp配置
        application live{ #rtmp推流请求路径 (切记路径错了会推不上流)
            live on; #开启实时
            hls on; #开启hls
            hls_path /www/rtmp; #rtmp推流请求路径,文件存放路径
            hls_fragment 5s; #每个TS文件包含5秒的视频内容

            #开始推流回调,url地址为java接口
            on_publish http://192.168.2.101:6540/rtmp/uploadRtmp;
            #推流停止回调,url地址为java接口
            on_done http://192.168.2.101:6540/rtmp/uploadRtmp;
        }
    }
}

在这里插入图片描述
至此,nginx 及 nginx-rtmp-module 部分配置完成 。

二、OBS推流测试

1,百度OBS下载及安装

2,添加来源,选择媒体源,选择本地的播放文件
在这里插入图片描述
在这里插入图片描述
3,添加来源后点击控件设置,配置OBS推流地址:
在这里插入图片描述

rtmp://192.168.2.122:1935/live // nginx的ip和application地址也就是推流地址
rtmp?token=123456 // 流名称,可以作为会话名称并且可以传递参数验证权限

单击开始推流,验证,查看服务器目录已经存在有流文件**(上面nginx配置的 hls_path 地址)**,并且在开始推流之前回调了所配置的java接口代码
在这里插入图片描述

以下为回调的java controller代码:

package cx.manager.client.demo.controller;

import cx.manager.common.vo.ResultPageVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@Controller
@RequestMapping("rtmp")
@Slf4j
public class RtmpController {

    @RequestMapping("/uploadRtmp")
    @ResponseBody
    public ResultPageVo uploadRemp(String token, HttpServletRequest request, HttpServletResponse response) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        System.out.println("参数数量:" + parameterMap.size());
        /**这三个参数是比较有用的参数
         tcurl:rtmp地址
         name:"rtmp://ngnix服务器地址/live/id"地址中去除推流地址的最后一个参数,可传入直播用户ID
         type:推流类型
         */
        System.out.println("tcurl:" + request.getParameter("tcurl"));
        System.out.println("name:" + request.getParameter("name"));
        System.out.println("type:" + request.getParameter("type"));
        //打印所有回调传过来的参数
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            System.out.println(entry.getKey() + "====================");
            for (String str : entry.getValue()) {
                System.out.println("\t" + str);
            }
        }
        return ResultPageVo.success();
//        try {
//            if (token.equals("123456")) {
//                return ResultPageVo.success();
//            } else {
//                response.setStatus(500);
//                return ResultPageVo.failure("token无效");
//            }
//        } catch (Exception e) {
//            response.setStatus(500);
//            return ResultPageVo.failure("token无效");
//        }
    }

    @GetMapping("/video")
    public String video(ModelMap modelMap) {

        modelMap.put("videoUrl", "rtmp://rtmp.test.orancrab.com:1935/live/rtmp");

        return "video";
    }
}

ResultPageVo 代码:

@ApiModel(value = "ResultPageVo", description = "页面通用响应VO")
public class ResultPageVo<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "响应码 1:成功 0:失败,其他根据实际情况自定义在ResultCode中,同时每个接口的特殊返回码需要注释。", dataType = "int", required = true)
    private Integer status;

    @ApiModelProperty(value = "消息提示", dataType = "string")
    private String message = "";

    @ApiModelProperty(value = "响应数据", dataType = "object")
    private T data;

    @ApiModelProperty(value = "响应数据", dataType = "object")
    private Object spareData;

    private ResultPageVo(Integer status) {
        this.status = status;
    }

    private ResultPageVo(Integer status, String message) {
        this.status = status;
        this.message = message;
    }

    private ResultPageVo(Integer status, T data) {
        this.status = status;
        this.data = data;
    }

    private ResultPageVo(Integer status, String message, T data) {
        this.status = status;
        this.message = message;
        this.data = data;
    }

    public static ResultPageVo<Void> success() {
        return new ResultPageVo<Void>(ResultCode.SUCCESS.status(), ResultCode.SUCCESS.message());
    }

    public static <T> ResultPageVo<T> success(T data) {
        return new ResultPageVo<T>(ResultCode.SUCCESS.status(), ResultCode.SUCCESS.message(), data);
    }

    public static <T> ResultPageVo<T> success(String message, T data) {
        return new ResultPageVo<T>(ResultCode.SUCCESS.status(), message, data);
    }

    public static ResultPageVo<Void> failure() {
        return new ResultPageVo<Void>(ResultCode.FAILURE.status(), ResultCode.FAILURE.message());
    }

    public static ResultPageVo<Void> failure(String message) {
        return new ResultPageVo<Void>(ResultCode.FAILURE.status(), message);
    }

    public static <T> ResultPageVo<T> failure(T data) {
        return new ResultPageVo<T>(ResultCode.FAILURE.status(), ResultCode.FAILURE.message(), data);
    }

    public static <T> ResultPageVo<T> failure(String message, T data) {
        return new ResultPageVo<T>(ResultCode.FAILURE.status(), message, data);
    }

    public static ResultPageVo<Void> create(ResultCode resultCode) {
        return new ResultPageVo<Void>(resultCode.status(), resultCode.message());
    }

    public static <T> ResultPageVo<T> create(ResultCode resultCode, T data) {
        return new ResultPageVo<T>(resultCode.status(), resultCode.message(), data);
    }

    public static ResultPageVo<Void> create(Integer status) {
        return new ResultPageVo<Void>(status);
    }

    public static ResultPageVo<Void> create(Integer status, String message) {
        return new ResultPageVo<Void>(status, message);
    }

    public static <T> ResultPageVo<T> create(Integer status, T data) {
        return new ResultPageVo<T>(status, data);
    }

    public static <T> ResultPageVo<T> create(Integer status, String message, T data) {
        return new ResultPageVo<T>(status, message, data);
    }

    public Integer getStatus() {
        return status;
    }

    public String getMessage() {
        return message;
    }

    public T getData() {
        return data;
    }

    public Object getSpareData() {
        return spareData;
    }

    public void setSpareData(Object spareData) {
        this.spareData = spareData;
    }

    @Override
    public String toString() {
        return "ResultPageVo{" +
                "status=" + status +
                ", message='" + message + '\'' +
                ", data=" + data +
                ", spareData=" + spareData +
                '}';
    }
}

ResultCode 代码:

public enum ResultCode {

    //带消息的响应码
    SUCCESS(1, "成功"),
    FAILURE(0, "失败"),//其他失败,全部走这里  请注意
    TOKEN_ERROR(10, "token验证失败"),
    PERMISSION_ERROR(11, "权限不足");

    private Integer status;

    private String message;

    ResultCode(Integer status) {
        this.status = status;
    }

    ResultCode(Integer status, String message) {
        this.status = status;
        this.message = message;
    }

    public Integer status() {
        return status;
    }

    public String message() {
        return message;
    }

}

只做了个简单测试,可根据这些参数完善后台,实现用户推流开始把用户ID和推流地址存入redis或其他高性能存储,前台展示当前直播的用户,点击用户返回推流地址,实现直播,用spring boot写的

三、http拉流播放

拉流地址:rtmp://192.168.2.122:1935/live/rtmp

1,百度VLC下载及安装

2,安装好之后选择媒体 -> 流,选择网络,输入流地址后开始拉流

在这里插入图片描述
输入后点击串流直接下一步到完成就好了
在这里插入图片描述
最后看到已经拉取到流了

3,使用网络播放器进行验证

(网络拉流播放器地址:http://www.cutv.com/demo/live_test.swf)
RTMP拉流地址:rtmp://192.168.2.122:1935/live/rtmp(和VLC拉流地址一样)
在这里插入图片描述
验证通过,已经可以拉到流了。。。。。。。

4,使用移动端app设置推流与h5拉流测试

安卓推流App下载地址(小米9可用,其他机型没试,IOS自己在网上找):https://download.youkuaiyun.com/download/u012946310/11170486

下载好后打开APP点击左上角 -> Profile 里面编辑推流地址和其他参数,推流地址就是之前的推流地址
在这里插入图片描述
4-1,h5播放页面代码(页面需要放在服务容器里面运行,如nginx、tomcat等,电脑需要安装flash,手机端不支持),拉流地址改成自己的流地址就可以了

<html>  
  <head>  
  <title>视频直播</title>  
  <meta charset="utf-8">  
  <link href="http://vjs.zencdn.net/5.5.3/video-js.css" rel="stylesheet">  
  <!-- If you'd like to support IE8 -->  
  <script src="http://vjs.zencdn.net/ie8/1.1.1/videojs-ie8.min.js"></script>  
</head>  
<body>  
  <h1>直播间</h1>
  <h1>本地测试</h1>
  <h2>推流命令:/usr/local/ffmpeg/bin/ffmpeg -re -i rtmp.mp4 -f flv rtmp://192.168.2.122:1935/live/rtmp?token=123456</h2>
  <h2>拉流地址:rtmp://192.168.2.122:1935/live/rtmp?token=123456</h2>
  <h1>远程测试</h1>
  <h2>推流地址:</h2>
  <h2>播放地址:http://cx.manager.test.orancrab.com/client_demo/rtmp/video</h2>
 <video id="my-video" class="video-js" controls preload="auto" width="640" height="300"  
 poster="http://ppt.downhot.com/d/file/p/2014/08/12/9d92575b4962a981bd9af247ef142449.jpg" data-setup="{}">
     <!-- src=推流地址,需要改成自己的推流地址 -->
    <source src="rtmp://192.168.2.122:1935/live/rtmp" type="rtmp/flv">
    <!-- 如果上面的rtmp流无法播放,就播放hls流 -->  
    <!-- <source src="http://10.10.5.119/live/livestream.m3u8" type='application/x-mpegURL'> -->  
    <p class="vjs-no-js">播放视频需要启用 JavaScript,推荐使用支持HTML5的浏览器访问。  
      To view this video please enable JavaScript, and consider upgrading to a web browser that  
      <a href="http://videojs.com/html5-video-support/video.ftl" target="_blank">supports HTML5 video</a>
    </p>  
 </video>  
 <script src="http://vjs.zencdn.net/5.5.3/video.js"></script>  
</body>  
</html> 

4-2,搭建完成,运行页面测试
在这里插入图片描述

五、结尾

到此一个简单的 nginx + rtmp 搭建流媒体服务器,完成!虽然不是一个完整的例子,但是核心就是以上这些,大家可以在次基础上扩展,有什么不妥的地方希望大家指正,共同学习

【配置环境】安装Ffmpeg音视频编解码工具和搭建EasyDarwin开源流媒体服务器 ffmpeg音视频编解码工具和EasyDarwin流媒体服务器搭建,测试将电脑桌面实时推流到服务器,然后进行拉流,拉流效果有直播的感觉 阅读详情

相关推荐

win11下,RTMP流媒体服务器保姆级教程

本片博客将详细介绍如何搭建一个RTMP流媒体服务器,包含源码下载,编译常见问题解决方法以及流媒体测试,最后讲解了如何利用obs软件实现推流。

君莫笑lucky的博客 2783

windows环境下,搭建RTMP视频推流服务器

介绍如何在windows环境下,如何快速地搭建RTMP服务器

朱豪凯的博客 2万+

直播平台流媒体服务器搭建(Linux+Nginx+RTMP)

近年来各大视频直播平台兴起,直播技术也愈发成熟,作为一个程序员,秉着“折腾”精神自己搭建了一个直播用的流媒体服务器,现在来和大家分享一下搭建的过程。

EricZwz的博客 6232

三、RTMP推流的原理及实现

打印 SRS 服务端的 log:发现 RTMP Client 连接成功,因为这个客户端也是在本机上启动的,所以地址也是 198.168.1.3。客户端会将设置好的 pcm 音频数据+ yuv 视频数据推到 SRS 服务端。注意:设置客户端请求的地址要和 SRS 服务启动的地址一样。然后拉流端会从SRS 服务端拉流播放。

qq_38800014的博客 4741

如何快速搭建一个直播平台?

如何搭建一个直播平台? 文章目录如何搭建一个直播平台?缘由原材料你需要懂开始操刀服务器搭建快速搭建访问开启直播!观看直播!拓展最后 缘由 首先呢,我是一个程序员,本篇文章简述如何快速使用现有的开源工具搭建一个直播平台,大概花了一天时间研究,现在要搭建也就是几分钟的事。 本来呢,是想要研究如何搭建一个视频流媒体服务器,为了使用手机或者电脑在任何地方都能看存在家里服务器上的电影、MV什么(~~小电影?...

XFhearrain的博客 9018

流媒体之从零实现搭建简单流媒体服务器,推流,拉流播放全景视频

一、直播与点播 直播:在我的理解中是实时录制的内容,类似各个晚会的实时直播过程,在现场采集图像的同时传输影像到网络上。 点播:是提前录制完成的内容,类似某些直播平台上根据观众的需求播放某些电影或经典电视剧。终端看到的内容是编辑好的视频文件,不是实时录制的。 本篇文章实现的功能就类似是点播,将本地的全景视频通过服务器传输到各个客户端。 二、实现直播或点播的关键步骤 1、搭建及配置流媒体服务器 ; 2、推流,将本地视频或直播视频以流媒体的形式推送给流媒体服务器 (可能会涉及格式转换); 3、拉流 ,从服务

Studing的博客 1万+

Windows流媒体服务器终极指南:5分钟快速搭建nginx-rtmp-win32

想要在Windows系统上快速部署专业级的实时流媒体服务吗?nginx-rtmp-win32项目正是你需要的解决方案。这个基于Nginx集成RTMP模块的Windows版本,让搭建直播和点播服务变得前所未有的简单。 ## 🚀 零基础极速入门 ### 环境准备与部署 1. **下载项目**: ```bash git clone https://gitcode.com/gh_mirr

gitblog_00019的博客 1053

nginx+rtmp简单实现直播服务端

使用 Nginx + Nginx-rtmp-module 在Ubuntu 中搭建简单的 rtmp 推流直播服务器。

技术引领业务创新 7万+

Windows流媒体服务器终极指南:nginx-rtmp-win32深度解析

nginx-rtmp-win32是专为Windows平台打造的实时音视频传输解决方案,集成了Nginx高性能服务器与RTMP流媒体协议支持,让用户能够快速部署专业的直播和点播服务。无需复杂编译,开箱即用,是个人创作者和小型企业的理想选择。 ## 🚀 五分钟快速启动方案 **获取项目源码**: ```bash git clone https://gitcode.com/gh_mirrors/n

gitblog_01069的博客 675

Nginx模块化服务器配置:流媒体与数据库集成

Nginx是当下使用非常广泛的高性能HTTP和反向代理服务器,由俄罗斯工程师Igor Sysoev开发。它的高性能和低资源消耗使其在处理高并发连接方面表现出色,特别适合于需要处理大量静态文件、反向代理、负载均衡等场景。在本章中,我们将从Nginx的基础架构开始了解,进一步探讨其工作原理,以及如何在各种IT环境中部署和优化Nginx,以实现最佳性能。# 示例:Nginx配置文件中的一个基本服务器块server {listen 80;

weixin_34520664的博客 929

局域网管理及交换机配置:VLAN划分、Trunk与跨VLAN通信实战

VLAN(虚拟局域网)通过逻辑划分广播域,解决局域网中广播风暴和安全隐患,其原理是基于802.1Q标签和PVID实现端口隔离与互通。掌握VLAN配置、Trunk链路和三层交换SVI技术,能有效提升网络性能与安全性,广泛应用于实验室、企业网和园区网。本文围绕局域网管理及交换机配置,详解从VLAN创建到跨VLAN通信的最小闭环,并分享避坑与ACL控制经验。

weixin_34226706的博客 405

搭建直播平台的基础,实现直播平台源码的架构

服务端流媒体服务器搭建 选择的流媒体服务器linux+nginx+rtmp_modulehttps://github.com/arut/nginx-rtmp-module 1.需要下载的其他包 2.上传至linux服务器解压添加模块编译 tar -zxvf nginx-1.9.9.tar.gz cd nginx-1.9.9 ./configure --prefix=/usr/local/nginx --add-module=../nginx-rtmp-module --with-htt...

QQ1981747098的博客 336

ZYNQ专题-7020驱动KSZ9031 PHY芯片

之所以有这篇文章,得益于Alinx的开发板。

Anitawen的博客 4965

用red5/nginx+obs+jwplayer+websocket实现视频直播与弹幕

1、Linux环境准备 linux版的red5下载 https://github.com/Red5/red5-server/releases nginx-rtmp下载 ,使用linux的git命令:git clone https://github.com/arut/nginx-rtmp-module.git ( 如果没有git进行安装,yum install git) 二者选一就可以了,网上说n...

weixin_43271746的博客 1268

西门子CPU与汇川伺服通信与控制

第三方驱动器的配置内容和西门子的配置内容基本一致,基本上会一种即可知道其他品牌的配置默认报文,需要激活硬限位才能收到限位信号默认报文,原点信号不能实时输出到PLC;自定义报文,需要伺服端设置DIN点位。

大小曲奇的博客 1万+

【VS Code+Verilog+Vivado使用】(1)常用插件

VS Code + Verilog + Vivado联合使用说明

XDUryan的博客 5637

linux下搭建RTMP服务器

最近我在实现将本地avi视频推送到RTMP服务器进行显示,搭建一个rtmp代理服务器就必不可少。简单基本概念介绍: RTMP全称是Real Time Messaging Protocol(实时消息传输协议),rmtp是一种通讯协议。该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMPT/RTMPS/RTMPE等多种变种。RTMP是一种设计用来进行实时数据通信的网络协议,主要用来在Fla...

yihuanyihuan的博客 698

详细教程:如何使用elasticsearch 8.x进行向量搜索

大模型的热度使得向量数据库和embedding也成了ai领域的热门话题,有别于从头开始训练一个大模型或基于基础模型进行微调的方式,embedding检索相关上下文是对大模型进行定制的各种方法中成本最低、技术实现最便捷的方式。从技术实现的角度,

qq_50790981的博客 1万+

Nginx初接触-基于Nginx的rtmp流媒体直播服务器搭建

Nginx初接触 基于Nginx的rtmp流媒体直播服务器搭建 致读这篇文章的朋友 首先这个标题其实是有一定程度的欺骗性的,哪个初学Nginx或者没接触过Nginx的说搭就搭出一个这个东西。但是这个这个东西就在我身上发生了,说到底以我现在的技术水平让我说对Nginx的理解和认识,我就一句话那个是老毛子开发的一个很好用扩展性强的HTTP和反向代理服务(反向代理(Reverse P...

dgfbphw1372的博客 331

超临界二氧化碳再热再压缩布雷顿循环建模与先进控制

超临界二氧化碳布雷顿循环建模与先进控制研究 本文研究了超临界二氧化碳再热再压缩布雷顿循环系统的建模与控制。通过MATLAB/Simscape构建了包含压缩机、透平、回热器等关键组件的动态模型,并设计了基于模型预测控制(MPC)和自抗扰控制(ADRC)的多层控制策略。系统采用转速控制的压缩机、阀门开度控制的透平,以及可变热源加热器,实现了全动态分析。研究结果表明,MPC与ADRC混合控制方案相较于传统PID控制,功率超调降低至0.9%,效率波动控制在±0.08%,扰动恢复时间缩短至12秒。

AI的内部世界的博客 340

3.DJI-payload SDK自定义控件的设计:

自定义控件(Widget)是指负载运行时,在用户界面中显示的自定义 UI 控件,以帮助用户快速查看负载独特的设备状态,或者对负载设进行设置。这些 UI 控件可以显示在以下用户界面中。Pilot 2 应用程序;大疆智图;基于 MSDK 开发的应用程序。这种自定义控件并不是通过 MSDK 实现的,而是通过 PSDK 的配置实现的。。

哒宰的博客 770

nginx-rtmp-module搭建流媒体服务器实现直播

一.Nginx之——nginx-rtmp-module搭建流媒体服务器实现直播 查看软件版本 rpm -q 卸载该版本 rpm -e 离线安装包 链接:https://pan.baidu.com/s/1KtMo6S_YTmTA_2reRY0wyQ 提取码:qwer [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EtNbLgKL-1600840185211)(C:\Users\liuchao\AppData\Roaming\Typora\typora-user-imag

菜鸟天涯_的博客 646

卫星轨道坐标转换:轨道六根数到经纬高(经STK验证)

a:半长轴(km)e:偏心率i:轨道倾角(度)Ω:升交点赤经(度)ω:近地点幅角(度)ν:真近点角(度)

weixin_52370774的博客 170

nginx 搭建媒体流

https://github.com/illuspas/nginx-rtmp-win32 http://www.bubuko.com/infodetail-580061.html http://www.bubuko.com/infodetail-580061.html      

jueqi2010的专栏 134

SAP 与 Palantir 合作全景解析:这不是普通集成,而是把 ERP、数据语义层、云迁移与企业级 AI 串成一条价值链

SAP与Palantir的战略合作聚焦企业数字化转型核心痛点,通过深度技术整合构建"数据-决策-执行"闭环。合作包含四大主线:云迁移连续性保障、SAP业务数据云与Palantir平台对接、联合工程开发、高监管行业优先落地。技术实现上采用SAP认证插件,支持双向数据交互和实时业务动作触发。该合作突破了传统ERP系统局限,将业务语义与AI执行相结合,特别适合制造业供应链优化、财务争议处理等高价值场景,为企业在云迁移过程中实现业务连续性与智能化升级提供新范式。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 192

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

搭建Nginx+nginx-rtmp-module的hls流媒体服务器并用OBS进行推流

最近在做直播项目,查阅了一下相关资料然后成功搭建服务,在这里整理记录下实现过程以及踩过的坑。 一、直播协议简介: 首先,在搭建服务之前先了解下目前主流的几个直播协议: 1、RTMP: 实时消息传输协议,Real Time Messaging Protocol,是 Adobe Systems 公司为 Flash 播放器和服务器之间音频、视频和数据传输开发的开放协议。协议基于 TCP...

Ricartc的编程梦 2万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

上一篇: linux环境下安装git版本控制服务器
下一篇: 阿里云实时音视频直播鉴权java代码示例
hwmhehe
博客等级 码龄13年 86粉丝 106原创
评论 17
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值