为熊猫 TV 直播生成带弹幕的录播视频

2017-07-19 • Web 万象 • #弹幕 #熊猫tv #直播 #nodejs

最近在沉迷谜之声直播。由于有时候下班比较晚,赶不上开播,又偶尔对直播游戏感兴趣的,就会跑去找录播来看。这个主播十分好心,会在贴吧里上传自己的录播视频。然而由于主播自己的录播视频采用 obs 串流的同时录制,对弹幕肯定是无能为力的,于是就想着能不能通过什么办法把弹幕加上去。所幸,办法还是有的。

现在熊猫直播全站 https 后,弹幕数据都是走的 websocket 了,通过 Fiddler 之类的抓包工具可以轻松抓到。不过,知乎上有一篇详细的回答说明老版本弹幕格式,也有一些现成的项目用来解析弹幕,所以这里就不关注弹幕数据格式了。总而言之,我把这些东西封装成了一个 npm 库 pandan,可以通过 node.js 简单的获取一个房间的实时弹幕了。比如:

let room = new (require('pandan').Room)(426346)
room.on('room-danmaku', function ({data}) {
  console.log(`${data.from.nickName}: ${data.content}`)
})
room.join()

有了弹幕数据自然就好办多了。从抓到的数据包来看,有主播开播、下播事件,送礼、送竹子等事件,完全足够我生成弹幕了。通过一段小脚本,可以把弹幕格式转换成下面这个样子的 xml:

...
<d p="1830.6300048828,1,25,16777215,1415241251,0,Da8b0a0d,668464499">再见了我的青春</d>
<d p="1477.6800537109,1,25,52479,1415241254,0,35b92ad0,668464527">虐啊</d>
...

脚本比较丑,就不贴了,相关参数的解析可以看这篇文章。这里有个小问题,由于直播通常有几秒钟的 buffer,所以弹幕整个时效性会稍微延后一些。这个问题在你观看直播的时候不容易发现(因为大家都有延迟),但生成录播之后弹幕会很明显的延后。当然,解决起来也十分简单,将弹幕时间轴往前平移几秒钟就可以了。

然后祭出大杀器:danmaku2ass,一个能将弹幕转换成 ass 字幕的工具。执行类似这样的命令:

python3 danmaku2ass/danmaku2ass.py -o 2017-07-17-1942-09.ass -s 1152x648 -fn "Microsoft YaHei" -fs 30 -a 0.8 -dm 7 2017-07-17-1942-09.xml

就能生成 ass 字幕了。使用任何带字幕功能的播放器,都可以播放啦~看个例子:

example image

当然,并不是所有主播都会自己上传录播视频。如果你刚好也有这种需求,可以尝试在连接弹幕服务器之后,获取开播事件,并在开播之后通过 you-get 来获取直播录像。

User Mode Linux - 一个用户态的 Linux 内核

2017-03-07 • Linux 笔记 • #uml

User Mode Linux 可以在用户态启动一个 Linux。这使我们能在类似 OpenVZ 虚拟化技术的系统上,使用最新的 Linux 内核;甚至可以在非 root 用户下启动。

但有些 OpenVZ VPS 的 TOS 可能不允许你这么做;另外,这样可能会有一定的性能损失。

准备 rootfs 镜像

我们找一台 Ubuntu Server 来准备 rootfs。这个时候需要有 root 权限,因为你需要 mount 一个 loop 文件系统,chroot 改点东西之类的。

# 下载镜像
wget http://uk.images.linuxcontainers.org/images/alpine/3.1/amd64/default/20170305_17:50/rootfs.tar.xz
# 安装解压软件
apt install xz-utils
# 创建镜像,32 M 对于 alpine 是够用的
dd if=/dev/zero of=rootfs.img bs=1M count=32
mkfs.ext4 rootfs.img
# 把镜像挂到 loop 上
mkdir rootfs
sudo mount -o loop rootfs.img rootfs
sudo tar xvf rootfs.tar.xz -C rootfs
# 给 root 设个密码
sudo chroot rootfs /bin/sh
  passwd
  exit
# 清理
sudo umount rootfs
rmdir rootfs

此时 rootfs.img 已经做好了。

编译内核

我们继续用 ubuntu server 来编译 UML 内核。

sudo apt install build-essential kernel-package fakeroot libncurses5-dev libssl-dev ccache
# 抓内核源码
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.10.1.tar.xz
tar xvf linux-4.10.1.tar.xz
cd linux-4.10.1
make defconfig ARCH=um
make menuconfig ARCH=um
# 这里会出来一个界面让你配置内核,有茫茫多的参数可以选
# 大概找一些 linux 内核编译的文章可以参考吧
# 主要是 User Mode Linux 有一些特殊选项可以注意下,比如强制静态编译什么的
# 然后就开始正式编译啦
make ARCH=um
strip linux # 移除调试符号

编译过程可能比较慢。有时候会有一些库找不到啥的,apt 装一下就好。

获取 slirp

slirp 是用来在没有 root 的情况下联网的。

apt source slirp

这里获取到的 slirp 放到目标机器上编译,不需要在 ubuntu server 上搞了。

cd slirp-1.0.17/src
./configure
make CFLAGS="-I. -DUSE_PPP -DUSE_MS_DNS -DFULL_BOLT -fno-strict-aliasing -Wno-unused -std=gnu89" clean all

启动 UML

现在万事俱备,只欠东风了。

# 在 UML Host 上
# 把一些二进制文件放好
slirp=/home/oott123/uml/slirp/slirp-1.0.17/bin/slirp
uml=/home/oott123/uml/kernel/linux-4.10.1/linux
rootfs=/home/oott123/uml/alpine/rootfs.img
cow=/home/oott123/uml/machine/demo/data.cow # 放 copy-on-write 数据的地方
export TMPDIR=/tmp
$uml rw ubda=$cow,$rootfs mem=128M eth0=slirp,,$slirp

配置网络

启动之后你可能会发现没有网络。不用担心,改改网络配置:

# 在 UML 里
vi /etc/network/interfaces
#####
auto eth0
iface eth0 inet static
address 10.0.2.15
gateway 10.0.2.2
netmask 255.255.255.0
dns-nameservers 10.0.2.3
hostname $(hostname)
#####
/etc/init.d/networking restart
echo 'nameserver 114.114.114.114' > /etc/resolv.conf
# 测试网络
wget -O- myip.ipip.net
# 安装软件
apk update
apk add curl
curl myip.ipip.net
# 关闭 UML
halt

与主机交互

或许你需要将 UML 内的端口转发到主机上。

# 在主机上
vi ~/.slirprc
redir 2222 22

或许你需要访问主机的文件系统。

# 在 UML 上,把 UML 内的 /mnt/home 映射到 /home
# 注意权限问题、注意两边不要同时读写
mkdir /mnt/home
mount none /mnt/home -t hostfs -o /home

2016: 我的浏览器 A - Z

2016-12-21 • Web 万象 • #浏览器 #我的浏览器a-z

A: https://aoishi.[REMOVED] 自己服务器的管理面板
B: http://bbs.i-cassell-you.com/forum.php 还是卡院
C: http://civitas.soobb.com/ 多少年没上了……
D: https://www.dnspod.cn/ DNSPod 有几个域名在上面
E: http://easy-admin.[REMOVED] ???已经是我记不起来的东西了
F: http://fiddle.jshell.net/ 呃……其实我用得不是很多
G: https://gitlab.com/ Ainou 的代码托管在那,所以经常去
H: http://hicivitas.com/ 以前兼职公司的官网
I: http://www.ip138.com/ …………大概是经常看自己 ip
J: http://jd.com/ 已经不怎么上淘宝了,狗东比较舒服
K: http://kuler.adobe.com/ 一个配色工具,可能是因为在收藏夹吧,平时不怎么用
L: http://logcg.com/ 这是谁的博客啊……完全不记得访问过了
M: https://mp.weixin.qq.com/ 微信公众平台……嗯最近可能是上得比较多
N: http://notes.jetienne.com/ 这又是谁的博客了……不记得了
O: http://openshift.redhat.com/ 我感觉今年我应该没上过
P: http://piao-tech.blogspot.com/ 怎么越来越离谱了
Q: http://qzone.qq.com/ ……啥。。
R: http://redis.io/ 嗯……倒是经常去查文档
S: https://suiyu.xyz/ 偶尔会写日记
T: http://tower.im/ 好用的团队协作工具呢……不过现在也不怎么用了
U: http://upyun.com/ 偶尔会上去配一下 CDN
V: https://v2ex.com/ 毫无悬念
W: http://weibo.com/ 其实我最近比较少上了……
X: http://xiumima.com/ 呃……社工库么
Y: http://yeah.net/ 偶尔会上网易邮箱看看
Z: https://zhihu.com/ 知乎倒是常去看的

总之,通过浏览器,可以看出一个趋势:我使用浏览器浏览不同的 web 网站的时间越来越少了——大部分网站我根本想不起来。而更多的时间,可能花在了刷手机上。移动互联网近年来确实是势不可挡,我也不得不沦陷了。

唯一不变的,大概是 Web 的信仰——以及,今年我还在坚持使用 Firefox 浏览大部分网页。

清空 Mac QQ 的最近表情列表

2016-12-06 • 辣鸡水果 • #QQ #mac

更新 Mac QQ 之后,最近发送过的表情变成了一大片惊讶,如图:

惊讶的 Mac QQ

不管发什么表情这些顺序都不会变,简直坑爹。去 QQ 的存储目录找了一下,发现删掉以下文件后就会好:

HistoryFacesStack_V52.archive
HistoryFacesList_V52.archive

这些文件位于 ~/Library/Application Support/QQ/(QQ号)/CustomFaceConfig.db(非沙盒)或 ~/Library/Containers/com.tencent.qq/Data/Library/Application Support/QQ/(QQ号)/CustomFaceConfig.db(沙盒)下。

删了以后,重启两次 QQ,果断好了:

不再惊讶的 Mac QQ

Unmanaged Exports 在中文系统下报错 syntax error at token '{' 问题

2016-05-13 • M$ 大法 • #c# #.net

UnmanagedExports 是一个可以在 C# 下生成类 c api 的 dll 的工具。

不过这玩意儿在中文系统下编译,可能会产生如下报错:

C:\Users\Administrator\AppData\Local\Temp\tmp6C70\adddll.il(60) : error : syntax error at token '{' in:   { AddDll  

解决方法很简单,换成英文系统即可。

至于啥原理,我也不知道。写下来避免后人踩坑……如果有哪位同仁知道怎么回事,也请告诉我~

友情链接