Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >linux服务器开发实战(一)——排查Flamingo服务端一个崩溃的问题

linux服务器开发实战(一)——排查Flamingo服务端一个崩溃的问题

作者头像
范蠡
发布于 2018-09-29 09:59:58
发布于 2018-09-29 09:59:58
1.6K00
代码可运行
举报
运行总次数:0
代码可运行

我的flamingo服务器(关于flamingo可以参看这里)最近在杀掉进程(如使用Ctrl + C或者kill + 程序pid)偶尔会出现崩溃问题,虽然这个问题没多大影响,因为进程本来就马上要死了,在退出的过程中崩溃也就无所谓了,但是本着严谨和求知的态度,我还是排查了一下。下面记录一下debug的过程,希望对读者有所启发。

正常情况下,我的程序处理了Ctrl+C信号时,会走正常的退出流程,预想的程序不会崩溃的,但实际还是崩溃了。

主线程是一个EventLoop无限循环,同时程序接收到Ctrl+C信号时,设置主线程退出标志。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 int main(int argc, char* argv[])
 2  {  
 3    //设置信号处理
 4    signal(SIGCHLD, SIG_DFL);
 5    signal(SIGPIPE, SIG_IGN);
 6    signal(SIGINT, prog_exit);
 7    signal(SIGTERM, prog_exit);
 8
 9    //省略无关代码...
10
11    g_mainLoop.loop();
12
13    return 0;
14}

信号处理程序如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1void prog_exit(int signo)
2   {
3    std::cout << "program recv signal [" << signo << "] to exit." << std::endl;
4
5    g_mainLoop.quit();
6
7}

通过日志也看不到对于排查崩溃现象的有任何帮助的日志信息,于是启用linux的linux的coredump文件生成机制,某次产生了如下coredump文件:

于是使用gdb调试查看一下崩溃调用堆栈(第一步使用命令gdb 可执行文件名称 core文件名,第二步使用bt命令查看崩溃堆栈):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1[zhangyl@iZ238vnojlyZ myimserver]$ gdb mychatserver core.9798 
 2GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7
 3   Copyright (C) 2013 Free Software Foundation, Inc.
 4   License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 5   This is free software: you are free to change and redistribute it.
 6   There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
 7   and "show warranty" for details.
 8   This GDB was configured as "x86_64-redhat-linux-gnu".
 9   For bug reporting instructions, please see:
10   <http://www.gnu.org/software/gdb/bugs/>...
11   Reading symbols from /home/zhangyl/myimserver/mychatserver...done.
12   [New LWP 9798]
13   [New LWP 9802]
14   [New LWP 9804]
15   [New LWP 9800]
16   [New LWP 9803]
17   [New LWP 9801]
18   [New LWP 9805]
19   [Thread debugging using libthread_db enabled]
20   Using host libthread_db library "/lib64/libthread_db.so.1".
21   Core was generated by `./mychatserver -d'.
22   Program terminated with signal 11, Segmentation fault.
23   #0  0x00000000004f5d3f in FixedBuffer<4000000>::avail (this=0x7f7067564010) at /home/zhangyl/myimserver/base/asynclogging.h:45
24   45              int avail() const { return static_cast<int>(end() - cur_); }
25Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.6.x86_64 libgcc-4.8.5-11.el7.x86_64 libstdc++-4.8.5-11.el7.x86_64
26(gdb) bt
27#0  0x00000000004f5d3f in FixedBuffer<4000000>::avail (this=0x7f7067564010) at /home/zhangyl/myimserver/base/asynclogging.h:45
28#1  0x00000000004f4e20 in AsyncLogging::append (this=0x7ffd5d58ad50, 
29    logline=0x7ffd5d58fe70 "20180820 15:46:06 DEBUG ~EventLoop EventLoop destructs in other thread - eventloop.cpp:87\n", len=90)
30    at /home/zhangyl/myimserver/base/asynclogging.cpp:98
31#2  0x000000000053bfc8 in asyncOutput (msg=0x7ffd5d58fe70 "20180820 15:46:06 DEBUG ~EventLoop EventLoop destructs in other thread - eventloop.cpp:87\n", len=90)
32    at /home/zhangyl/myimserver/chatserversrc/main.cpp:33
33#3  0x00000000004f205d in Logger::~Logger (this=0x7ffd5d58fe60, __in_chrg=<optimized out>) at /home/zhangyl/myimserver/base/logging.cpp:149
34#4  0x0000000000504bf1 in net::EventLoop::~EventLoop (this=0x7d1c00 <g_mainLoop>, __in_chrg=<optimized out>) at /home/zhangyl/myimserver/net/eventloop.cpp:87
35#5  0x00007f7067d79e69 in __run_exit_handlers () from /lib64/libc.so.6
36#6  0x00007f7067d79eb5 in exit () from /lib64/libc.so.6
37#7  0x00007f7067d62b1c in __libc_start_main () from /lib64/libc.so.6
38#8  0x00000000004f0ba9 in _start ()
39(gdb)

崩溃的根源在于堆栈#0,使用frame命令(frame 堆栈编号,如frame 0,表示切换到堆栈#0)切换到堆栈#0

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1(gdb) frame 0
2#0  0x00000000004f5d3f in FixedBuffer<4000000>::avail (this=0x7f7067564010) at /home/zhangyl/myimserver/base/asynclogging.h:45
345              int avail() const { return static_cast<int>(end() - cur_); }
4(gdb) p this
5$1 = (const FixedBuffer<4000000> * const) 0x7f7067564010
6(gdb)

使用print命令(简写成p)查看下当前对象的this指针,this指针时一个地址值,但是不代表这个对象有效,再使用print命令查看一下这个对象本身的数据(p *this),发现这个对象已经失效:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1(gdb) p *this
2Cannot access memory at address 0x7f7067564010
3(gdb)

这个对象为啥失效呢?而且堆栈#3堆栈#4显示的是在EventLoop里面调用日志类Logger的析构函数。先看下堆栈#4处的函数代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1EventLoop::~EventLoop()
 2{    
 3    LOG_DEBUG << "EventLoop destructs in other thread";
 4
 5    //std::stringstream ss;
 6    //ss << "eventloop destructs threadid = " << threadId_;
 7    //std::cout << ss.str() << std::endl;
 8
 9    wakeupChannel_->disableAll();
10    wakeupChannel_->remove();
11    ::close(wakeupFd_);
12    t_loopInThisThread = NULL;
13}

除了打印一行日志,也没有和日志Logger类相关的代码,且EventLoop也没有与Logger类相关的成员变量(也就是无隐式析构)。我们再看下堆栈#3处的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1Logger::~Logger()
 2{
 3    impl_.finish();
 4    const LogStream::Buffer& buf(stream().buffer());
 5    g_output(buf.data(), buf.length());
 6    if (impl_.level_ == FATAL)
 7    {
 8        g_flush();
 9        abort();
10    }
11}

崩溃的地方就是g_output(buf.data(), buf.length()); 而这个buf的内容正好就是EventLoop析构函数里面打印的一行日志:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
EventLoop destructs in other thread

那么这个g_output为啥会调用AsyncLogging::append函数呢?(参考堆栈#1)。我们通过全局搜索发现g_output是一个全局变量,并且在定义时已经有初始值:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Logger::OutputFunc g_output = defaultOutput;

而初始值defaultOutput的行为就是将日志输出到控制台:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1void defaultOutput(const char* msg, int len)
2  {
3    size_t n = fwrite(msg, 1, len, stdout);
4    //FIXME check n
5    (void)n;
6}

fwrite中的第二个参数是1在linux中0代表标准输入控制台,1代表标准输出控制台,2代表错误输出控制台

我们其实在main函数中,改变了日志的输出行为,让日志即可以输出到控制台也能输出到日志文件中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1EventLoop g_mainLoop;
 2AsyncLogging* g_asyncLog = NULL;
 3void asyncOutput(const char* msg, int len)
 4  {
 5    if (g_asyncLog != NULL)
 6    {
 7        g_asyncLog->append(msg, len);
 8        std::cout << msg << std::endl;
 9    }
10}
11
12void asyncOutput(const char* msg, int len)
13   {
14    if (g_asyncLog != NULL)
15    {
16        g_asyncLog->append(msg, len);
17        std::cout << msg << std::endl;
18    }
19}
20
21int main(int argc, char* argv[])
22  {
23    //省略无关代码
24    std::string strLogFileFullPath(logfilepath);
25    strLogFileFullPath += logfilename;
26    Logger::setLogLevel(Logger::DEBUG);
27    int kRollSize = 500 * 1000 * 1000;
28    AsyncLogging log(strLogFileFullPath.c_str(), kRollSize);
29    log.start();
30    g_asyncLog = &log;
31    Logger::setOutput(asyncOutput);
32
33    //省略无关代码
34
35    g_mainLoop.loop();
36
37    return 0;
38}

看到这里问题就来了,当main函数执行完毕,即出了main函数的作用域,log对象已经销毁。此时正好正在销毁全局对象g_mainLoop,此时调用EventLoop的析构函数,在其析构函数中打印“EventLoop destructs in other thread”这行日志,仍然会调用asyncOutput函数,但是此时g_asyncLog 已经是一个无效的指针了,且不是空指针(野指针),所以你调用它的append方法必然会引起内存问题。

如何改正这个问题呢? 方法有多种,方法一就是在g_mainLoop.loop()后面加上一行,将全局指针对象g_asyncLog显式设置为空指针,这样EventLoop里面的析构函数打印的日志就不会打印了,因为asyncOutput函数中已经做了空指针判断。代码改成如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1int main(int argc, char* argv[])
 2  {
 3    //省略无关代码
 4    std::string strLogFileFullPath(logfilepath);
 5    strLogFileFullPath += logfilename;
 6    Logger::setLogLevel(Logger::DEBUG);
 7    int kRollSize = 500 * 1000 * 1000;
 8    AsyncLogging log(strLogFileFullPath.c_str(), kRollSize);
 9    log.start();
10    g_asyncLog = &log;
11    Logger::setOutput(asyncOutput);
12
13    //省略无关代码
14
15    g_mainLoop.loop();
16    g_asyncLog = NULL;
17
18    return 0;
19}

这种解决方案缺点是丢了部分日志,方法二就是将这个log对象也申明成全局变量,即将g_asyncLog改成对象而不是指针我们这里采用方法二,修改后的代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1EventLoop g_mainLoop;
 2
 3AsyncLogging g_asyncLog;
 4
 5void asyncOutput(const char* msg, int len)
 6  {
 7    g_asyncLog.append(msg, len);
 8    std::cout << msg << std::endl;
 9}
10
11int main(int argc, char* argv[])
12  {
13    //无关代码省略...
14    std::string strLogFileFullPath(logfilepath);
15    strLogFileFullPath += logfilename;
16    Logger::setLogLevel(Logger::DEBUG);
17    int kRollSize = 1024 * 1024 * 1024;
18    //AsyncLogging log(strLogFileFullPath.c_str(), kRollSize);
19    g_asyncLog.setBaseName(strLogFileFullPath.c_str());
20    g_asyncLog.setRollSize(kRollSize);
21    g_asyncLog.start();
22    Logger::setOutput(asyncOutput);
23
24    //无关代码省略...
25
26    g_mainLoop.loop();
27
28
29    return 0;
30}

改完之后,重新编译程序,我们要验证一下,我们让程序接收Ctrl + C信号,由于gdb默认会自己处理Ctrl + C指令(行为是让gdb中断下来接收用户输入),我们可以修改gdb的设置让gdb不要处理这个信号,而是把这个信号传给我们的程序,在gdb中执行如下指令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
handle SIGINT nostop print pass 

这样程序就能响应Ctrl + C了SIGINT是Ctrl + C产生的信号值)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1(gdb)  handle SIGINT nostop print pass 
 2SIGINT is used by the debugger.
 3Are you sure you want to change it? (y or n) y
 4Signal        Stop      Print   Pass to program Description
 5SIGINT        No        Yes     Yes             Interrupt
 6(gdb) r
 7Starting program: /home/zhangyl/flamingoserver/chatserver 
 8[Thread debugging using libthread_db enabled]
 9Using host libthread_db library "/lib64/libthread_db.so.1".
10[New Thread 0x7ffff442b700 (LWP 11460)]
11[New Thread 0x7ffff3c2a700 (LWP 11461)]
12[Thread 0x7ffff3c2a700 (LWP 11461) exited]
1320180820 22:00:27 INFO  show databases - DatabaseMysql.cpp:93
14
1520180820 22:00:27 INFO  CMysqlManager::_IsDBExist, find database(flamingo) - MysqlManager.cpp:195
16
1720180820 22:00:27 INFO  desc t_user - DatabaseMysql.cpp:93
18
1920180820 22:00:27 INFO  desc t_user_relationship - DatabaseMysql.cpp:93
20
2120180820 22:00:27 INFO  desc t_chatmsg - DatabaseMysql.cpp:93
22
2320180820 22:00:27 INFO  SELECT f_user_id, f_username, f_nickname, f_password,  f_facetype, f_customface, f_gender, f_birthday, f_signature, f_address, f_phonenumber, f_mail, f_teaminfo FROM t_user ORDER BY  f_user_id DESC - DatabaseMysql.cpp:93
24
2520180820 22:00:27 INFO  current base userid: 0, current base group id: 268435455 - UserManager.cpp:111
26
27[New Thread 0x7ffff3c2a700 (LWP 11462)]
28[New Thread 0x7ffff2a74700 (LWP 11463)]
29[New Thread 0x7ffff2273700 (LWP 11464)]
30[New Thread 0x7ffff1a72700 (LWP 11465)]
31[New Thread 0x7ffff1271700 (LWP 11466)]
32[New Thread 0x7ffff0a70700 (LWP 11467)]
33[New Thread 0x7fffd3fff700 (LWP 11468)]
34[New Thread 0x7fffd37fe700 (LWP 11469)]
3520180820 22:00:27 INFO  chatserver initialization completed, now you can use client to connect it. - main.cpp:139
36
37^C
38Program received signal SIGINT, Interrupt.
39program recv signal [2] to exit.
40Exit loop...
41Exit chatserver....
42[Thread 0x7ffff442b700 (LWP 11460) exited]
43[Thread 0x7fffd3fff700 (LWP 11468) exited]
44[Thread 0x7fffd37fe700 (LWP 11469) exited]
45[Thread 0x7ffff0a70700 (LWP 11467) exited]
46[Thread 0x7ffff1271700 (LWP 11466) exited]
47[Thread 0x7ffff1a72700 (LWP 11465) exited]
48[Thread 0x7ffff2273700 (LWP 11464) exited]
49[Thread 0x7ffff3c2a700 (LWP 11462) exited]
50[Thread 0x7ffff7fe5a80 (LWP 11459) exited]
51[Inferior 1 (process 11459) exited normally]
52(gdb) 

至此,我们验证并修复了该bug,这样程序在响应Ctrl + C或者用kill + pid杀死进程就可以走正常退出流程了,而不再崩溃。不知道你学到了没有?

小结一下: 通过上面的例子我们可以发现,作为一个合格的linux后台开发人员,我们不仅要熟悉业务代码本身,还要熟练适用gdb各种命令,同时对操作系统的一些机制也要了解(例如:如何设置程序崩溃以后产生core文件)。如果你还没有掌握,建议一定要好好练习一下gdb的使用。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 高性能服务器开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
摆脱客户端?网页发起直播势在必行!
近几年直播行业飞速发展,但是由于Web端这方面功能的长时间缺失,使得直播端以客户端为主;WebRTC 的出现使得网页也可以成为直播端。那么究竟WebRTC是什么呢?
保利威视频云
2020/05/07
3.2K0
摆脱客户端?网页发起直播势在必行!
实时音视频WebRTC介绍
简而言之,WebRTC就是W3C定的一个Web标准,用来做二进制数据传输用的,各浏览器只要支持WebRTC,就可以不通过插件,直接在Web端实现诸如音频、视频、文件等二进制数据的传输。方便之处在于:不需要再使用Flash、Silverlight之类的插件了。but!理想很丰满,现实往往很残酷,WebRTC从诞生之初到现在仍然还有很多地方布满了坑。
腾讯云-chaoli
2019/04/25
9.1K0
实时音视频WebRTC介绍
Web前端WebRTC攻略(二) 音视频设备及数据采集
2021年1月26日,W3C 和 IETF 同时宣布 WebRTC(Web Real-Time Communications,Web 实时通信)现发布为正式标准,标志着 WebRTC正式走进舞台。尽管如此,WebRTC 早已在视频会议和直播中得到了广泛的应用,成为了线上通信及协作服务的基石。IMWeb 团队是国内最早研究 WebRTC 的团队之一,在腾讯课堂、企鹅辅导等应用中都有实践。这是 WebRTC 系列的第二篇,希望可以帮助你更好的了解音视频。 一、音视频采集基本概念 在讲浏览器提供的用 JS 采集音
用户1097444
2022/06/29
3.9K0
Web前端WebRTC攻略(二) 音视频设备及数据采集
WebRTC 之媒体流与轨道
媒体流指的是访问设备后产生的数据流,轨道指的是 WebRTC 中的基本媒体单元。
前端小鑫同学
2022/12/26
1.4K0
JavaScript 是如何工作的:WebRTC 和对等网络的机制!
WebRTC,名称源自网页即时通信(英语:Web Real-Time Communication)的缩写,是一个支持网页浏览器进行实时语音对话或视频对话的API。
前端小智@大迁世界
2019/03/15
2.7K0
JavaScript 是如何工作的:WebRTC 和对等网络的机制!
WebRTC实现一个网页在线录制视频
电脑录制视频几乎不会用到,当有需要的时候就各种找软件找工具,并且都会找免费的。现在市场上肯定有很多符合需求,只是那么偶尔的情况下,而且使用场景不是那么多要求的情况下,一个网页在线直接录屏是不是非常nice。
wade
2022/12/02
2.1K0
WebRTC实现一个网页在线录制视频
从webrtc原理讲起,聊聊自助排障那些事
WebRTC作为实现前端互动和实时音视频的开源项目,已经被广泛应用与行业内的各个领域。本文以WebRTC实现实时通信的完整过程为线索,结合实际问题案例讲解下常见问的的排查思路,望读完本文可以了解WebRTC实现音视频通信的过程和一般腾讯云TRTC web端问题的排障思路。
singleli
2020/11/01
2.1K0
从webrtc原理讲起,聊聊自助排障那些事
实时音视频开发学习8 - 云端混流转码
云端混流主要用于CND直播观看和云端录制回放等场景中,需要将TRTC房间里的多路音视频流混合成一路。混流方式为MCU混流转码集群,其能将多路音视频流进行混合,并将最终生成的视频流分发给直播CDN和云端录制系统。
金林学音视频
2020/08/25
2.1K0
实时音视频开发学习8 - 云端混流转码
WebRTC 点对点直播
作者:villainthr WebRTC 全称为:Web Real-Time Communication。它是为了解决 Web 端无法捕获音视频的能力,并且提供了 peer-to-peer(就是浏览器
腾讯IVWEB团队
2017/03/13
10.5K0
一张图概括淘宝直播背后的前端技术 | 赠送多媒体前端手册
2020年,直播带货火爆全网。想一探淘宝直播背后的前端技术?本文将带你进入淘宝直播前端技术的世界。
音视频开发进阶
2020/11/10
3.1K0
一张图概括淘宝直播背后的前端技术 | 赠送多媒体前端手册
新知 | 直播架构方案解析及趋势探讨
‍‍ 腾讯云音视频的直播最早是基于QQ音视频能力开发出来的产品,至今深耕音视频领域超过20多年,积累了丰富的音视频和海量服务技术。今天的新知系列课,我们邀请到了腾讯云音视频的技术导师 —— 兰玉龙,为大家由浅入深的介绍一下音视频直播的基础概念以及技术趋势,同时和大家分享一些直播相关的技术以及行业应用,以便大家理解和更加方便地使用直播能力。 接下来的几周,每周四晚上7:30,我们都会在腾讯云音视频视频号、开源中国、InfoQ、51CTO、云+社区等多个平台进行课程直播,大家千万不要错过哦~ - 云直
腾讯云音视频
2021/11/26
1.7K0
Web前端WebRTC攻略(一) 基础介绍
随着互联网高速发展,以及即将到来的5G时代,WebRTC作为前端互动直播和实时音视频的利器,也是将前端开发者们不可错过的学习领域。如果你现在只是听过而已,那你可能要好好学习一番。 01  什么是WebRTC? WebRTC 全称是(Web browsers with Real-Time Communications (RTC) 大概2011年,谷歌收购了 GIPS,它是一个为 RTC 开发出许多组件的公司,例如编解码和回声消除技术。Google 开源了 GIPS 开发的技术,并希望将其打造为行业标准。 收
用户1097444
2022/06/29
2.8K0
Web前端WebRTC攻略(一) 基础介绍
音视频通信加餐 —— WebRTC一肝到底
最近需要搭建一个在线课堂的直播平台,考虑到清晰度和延迟性,我们一致认为使用 WebRTC 最合适。
杨成功
2022/09/22
1.2K0
音视频通信加餐 —— WebRTC一肝到底
实时音视频 TRTC 常见问题汇总---WebRTC篇
TRTC Web SDK 对浏览器的详细支持度,您可以查看 TRTC Web SDK 对浏览器支持情况。
腾讯视频云-Zachary
2019/11/15
23.4K3
实时音视频 TRTC 常见问题汇总---WebRTC篇
音视频应用:如何实现直播间连麦
‍ ‍ 这十年是音视频快速发展的十年,从互动娱乐和电商直播,到互联网会议和在线教育,最近火热的元宇宙,音视频是基础能力之一。 从直播间连麦场景出发,可以了解互联网音视频所涉及的技术,由此深入学习音视频的相关技术点,可以让自己建立完整的音视频技术体系,快速应用到线上业务中。 Introduction 2015年音视频直播迎来了大的爆发,典型的场景是互动娱乐和电商直播。2017年WebRTC迅猛发展,典型场景是互联网会议、在线教育、低延迟直播和互动。2021年开始炒元宇宙,音视频也是基础能力之一。 音视频
Winlin
2022/07/01
7K0
音视频应用:如何实现直播间连麦
web多媒体技术在视频编辑场景的应用
大家上午好,很高兴来到咱们腾讯LIVE开发者大会。我今天分享的web多媒体技术在视频编辑场景的应用是个非常有意思的主题,希望大家能有所收获。 首先介绍下自己,我是袁运辉,2010年就加入了腾讯,目前主要在腾讯云视频中心负责web团队。 视频云的web团队是一个偏多媒体前端技术的团队,致力于为客户提供更多创新的场景化云服务,近期我们在视频制作领域中有一些实践经验,我觉得和前端技术以及大会的主题都比较契合,所以非常有意愿来这与大家做一次分享。 我的分享主要分为四部分:第一部分介绍下业务背景;第二部分介绍
腾讯技术工程官方号
2020/09/09
4.4K1
TRTC Web SDK + 播放器 Web SDK 实现 CDN 直播观看
在使用腾讯的TRTC Web SDK可以在Web端实现主播的直播流推送和观众的拉流观看,但是由于 TRTC 采用 UDP 协议进行传输音视频数据,在直播时可能会遇到一些问题:
yuliang
2021/03/21
7.4K0
TRTC学习之旅(五)-- 自定义视频采集
在有些开发场景下,我可能在视频的时候不需要播放摄像头的内容,我需要播放页面上某一块区域的内容(动画、视频等)。这个时候就需要使用到自定义视频采集的方式去实现了。
黑眼圈云豆
2020/07/12
1.6K0
低延时高并发视频直播技术WebRTC,在安防视频监控中的应用实践
Web Real-Time Communication(Web实时通信,WebRTC)由一组标准、协议和JavaScript API组成,用于实现浏览器之间(端到端)的音频、视频及数据共享。WebRTC使得实时通信变成一种标准功能,任何Web应用都无需借助第三方插件和专有软件,而是通过简单地JavaScript API即可完成。
TSINGSEE青犀视频
2021/12/23
1.9K0
腾讯云音视频的创新技术、多元场景以及出海洞察
近年来,腾讯云音视频在音视频技术领域不断突破创新,从采集、编码、传输加速、云端媒体处理、分发到解码,不断探索前沿技术,并将其广泛应用于多元化的场景中。与此同时,在海外市场的实践中,腾讯云音视频积累了丰富的经验和对市场的深刻洞察。
腾讯云音视频
2024/01/01
9410
腾讯云音视频的创新技术、多元场景以及出海洞察
推荐阅读
相关推荐
摆脱客户端?网页发起直播势在必行!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档