FFmpeg 执行音视频格式转换、拼接和剪切处理非常好使,最近在项目中需要对音视频原文件进行处理,为了省事儿我直接在 code 里调用 shell 来执行相关命令。

但是这样搞往往会留坑,比如说当同名输出文件已存在于文件系统中时,terminal 控制台就会弹出交互请求是否覆盖已有文件,这对于程序来讲太不友好了,我需要一波默认覆盖的操作。

解决的问题办法就是在传参时添加 -y 参数,之后的问题就迎刃而解了。

# video concat 
ffmpeg -y -i "concat:8553.ts|7166.ts" -vcodec copy 55216.flv

# video cut
ffmpeg -y -i 4134.ts -ss 00:00:05.0 -t 00:00:20.0 -vcodec copy -async 1 slice.mp4

# extract the specific frame
ffmpeg -y -i 1.ts -f mjpeg -ss 3 -t 1  test1.jpg

# convert video to GIF
ffmpeg -y -i 1.ts -ss 4 -t 5 -r 5 -f gif -s 512x288 4.gif

Systemd integration

Systemd is now included in both the centos:7 and centos:latest base containers, but it is not active by default. In order to use systemd, you will need to include text similar to the example Dockerfile below:

FROM centos:7
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]

Dockerfile for systemd base image

This Dockerfile deletes a number of unit files which might cause issues. From here, you are ready to build your base image.

$ docker build --rm -t local/el7-systemd .

Example systemd enabled app container

In order to use the systemd enabled base container created above, you will need to create your Dockerfile similar to the one below.

FROM local/el7-systemd
RUN yum -y install httpd; yum clean all; systemctl enable httpd.service
EXPOSE 80
CMD ["/usr/sbin/init"]

Build this image:

$ docker build --rm -t local/el7-systemd-httpd .

Running a systemd enabled app container

In order to run a container with systemd, you will need to mount the cgroups volumes from the host. Below is an example command that will run the systemd enabled httpd container created earlier.

$ docker run -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 local/el7-systemd-httpd

This container is running with systemd in a limited context, with the cgroups filesystem mounted. There have been reports that if you’re using an Ubuntu host, you will need to add -v /tmp/$(mktemp -d):/run in addition to the cgroups mount.

在 Docker 容器里跑 Python 程序时,我们经常遇到通过print函数或者logging 模块输出的信息在容器 log 中迷之失踪,过了好久又迷之出现。这是因为 Python 在写 stdout 和 stderr 的时候有缓冲区,导致输出无法实时更新进容器 log。

有如下几种方法解决:

1.增加环境变量
对于使用print函数打印的内容,在运行容器时增加环境变量PYTHONUNBUFFERED=0就可以解决。

2.配置 logging 的 stream 参数

import logging
logging.basicConfig(stream=sys.stdout)

这样,通过 logging 模块打印的日志都会直接写到标准输出 stdout。

或者自定义两个StreamHandler分别配置为输出到 stdout 和 stderr,来对不同 log 分别进行输出处理。

3.WSGI server 配置参数
如果是以 WSGI server 运行的 web 应用,以 gunicorn 为例,在 gunicorn 的启动命令中增加参数--access-logfile - --error-logfile -即可。

析构函数是 C++ 中一个非常重要的概念,析构函数 (destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。 析构函数往往用来做“清理善后” 的工作,例如在建立对象时用 new 开辟了一片内存空间,delete 则会调用析构函数后释放内存。

而在 Python 中没有专用的构造和析构函数,但是一般可以在__init____del__分别完成初始化和删除操作,以替代构造和析构。

但是 Python 社区中的许多人都不推荐使用 __del__,因为 Python 对对象使用了引用计数来管理,很多情况下是很难以估计是什么时候引用计数为 0 而造成销毁的,同时很多使用技巧告诉我们使用 Python 编程不用再过度优化内存使用,以避免写出 C++ 风格的代码。

在本文中,我们将明确如何来正确使用__del__

Continue reading

我带的实习生要开始搞 fpm 的落地和实现了,为了更加优雅的完成这个工具,整个 rpmbuild – Test – Beta – Production 生命周期充斥着各类异步场景。

0x00 Promise in Node.js

这段时间写大屏用 Node.js 积累了一些网络和文件操作上使用异步编程的经验,一般简单场景使用回调方式就能很好的解决问题,但当遇到比较复杂的逻辑时,为了避免 Callback Hell 的问题的,异步接口更好的处理办法就是使用 Promise 接口。

let promisify = (fn, receiver) => {
  return (...args) => {
    return new Promise((resolve, reject) => {
      fn.apply(receiver, [...args, (err, res) => {
        return err ? reject(err) : resolve(res);
      }]);
    });
  };
};

var fs = require("fs");
var readFilePromise = promisify(fs.readFile, fs); // Encapsulate Promise interface

readFilePromise("foo.json", "utf8").then(function(content){
    // normal
}).catch(function(err){
    // abnormal
})

题外话,JavaScript 从 ES8 开始支持基于 Promise 的 Async/Await 语法糖, 实现类似 Golang 协程采用同步方式写异步代码。

Continue reading

昨晚快下班的时候,蓝色港湾那家影院的客服小哥给我打电话说我们预定的那个包场被取消了,心态有点炸。今早到公司重新规划了路线,终于把周五 Building 的全套行程都确定下来了,明天消费升级改道去国贸。

中午有小姐姐来找我说他们新员工培训抽到了‘持续创新’的主题,打算把我做 AI 沟通助手的过程拍成一部 VCR,于是我们很愉快的聊了下研发细节,话说上次涉足演艺圈事业已经是快一年前的事了,明少当时约了一票好友一起造了一晚上,记得那时候坐我左手边的姑娘气质特别好,唱霉霉的歌也特有感觉。


转眼间接口开放平台野蛮生长了很长一段时间了,一直没有一个很正式的测试环境,每次做新需求都是从 git 上把代码拉下来重新起套新环境,这里面存在很多坑,比如 Python3 版本升级之后 virtualenv 中的 mysql 依赖就装不上了

ModuleNotFoundError: No module named 'ConfigParser'

查阅相关文档之后发现在 Python3 版本升级后,ConfigParser.py 已经更名为 configparser.py 了,可以同前版本的处理办法一样,通过重命名解决问题,但是路子太野会给之后上量扩容满坑,所以得找找其他办法。

https://github.com/PyMySQL/PyMySQL

于是我找到了 mysql 的替代模块 PyMySQL,

pip3 install PyMySQL

如果还有报错,那么:

# Ubuntu
sudo apt-get install libmysqlclient-dev

# CentOS
sudo yum install python-dev mariadb-devel

PyMySQL 的玩儿法也更加优雅,特别对于多条数据的处理逻辑也更加线性易于理解。Continue reading

在做大屏可视化展示的时候,需要把大数据收敛聚合接口提供的数据以三个 Pie 图的形式展示在屏幕下方正中。

Burst of Celestial Fireworks

Screen Preview

下面就是我使用 Node 完成样式构造的 demo:

const StyledDivAllinline = styled.div`
text-align:center;
margin:0 auto;
padding:0;
clear:both;
`
// `inline-block` effect
const StyledSubdivAllinline = styled.div`
margin:0;
padding:0;
display:inline-block;
_display:inline;
*display:inline;
zoom:1;
`
// render
<StyledDivAllinline>
  <StyledSubdivAllinline>
    Hello, world
  </StyledSubdivAllinline>
  <StyledSubdivAllinline>
    HELLO, World
  </StyledSubdivAllinline>
  <StyledSubdivAllinline>
    Hail, Hydra
  </StyledSubdivAllinline>
</StyledDivAllinline>

今天和公司的设计师聊了聊 UBER 开源的基于 deck.gl 的地理数据可视化工具 kepler.gl,效果非常炸裂!

https://uber.github.io/kepler.gl/#/demo

在我使用的试用过程中,我发现这个 client-side web App 可以将动辄 20M+ 的 sample data 渲染时间控制在极短的时间内,不得不说现在前端框架的强劲,js统治世界#手动滑稽

下面整理一些 kepler.gl 提供的公开数据集,供以后查看使用吧。

  1. Open Data Paris The site of the open data approach of the City of Paris. You will find here all the datasets published by the services of the City and its partners.
  2. California Earthquakes The dataset contains a list of 2.5+ magnitude earthquakes in california. Information was generated using USGS website and contains multiple properties (location, magnitude, magtype) for each single entry.
  3. New York City cab rides The yellow and green taxi trip records include fields capturing pick-up and drop-off dates/times, pick-up and drop-off locations, trip distances, itemized fares, rate types, payment types, and driver-reported passenger counts.
  4. San Francisco elevation contour Physical Features – Elevation contours for San Francisco mainland and Treasure Island/Yerba Island. Based on San Francisco Elevation Datum.
  5. New york city population by census tract This dataset contains the 2010 Census tract map, joined with population data of NYC.
  6. San Francisco street tree map From DataSF, this dataset contains a list of dpw maintained street trees including planting date, species and location.
  7. England and Wales Commute Map This dataset shows location of residence and place of work, based on 2011 Census of residence of England and Wales. The data classifies people currently resident in each middle layer super output area, or higher area and shows the movement between their area of residence and workplace.
  8. $2+ million homes built in Los Angeles since 2006 Valuation and property description for parcels on the Assessor’s annual secured assessment rolls 2006 through 2017. This dataset excludes Cross Reference Rolls (89xx-series AssessorID).
  9. Travel Times from Uber Movement Uber Movement provides free and public access to travel times data derived from billions of Uber trips. Data is available under a Creative Commons Noncommercial Attribution License.
  10. 2017 Unemployment Rates for U.S. Counties 2017 labor force information from the Bureau of Labor Statistics joined with county shapefiles from the Census Bureau.

Ref

[1] https://github.com/uber-web/kepler.gl-data
[2] https://github.com/uber/kepler.gl
[3] https://uber.github.io/kepler.gl/#/demo

0x00 背景

由于生产环境中各类因素的影响,使得监控数据特别是时间序列数据里存在许多噪声。这些噪声严重影响了进一步的定量分析和数据挖掘,有必要预先去噪。

但是时间序列本身具有非线性和信噪比高的特点,采用传统的高斯去噪、中值滤波等方法往往存在诸多缺陷。而小波理论是根据时频局部化的要求而发展起来的,具有自适应和数学显微镜性质,特别适合非平稳、非线性信号的处理。

0x01 小波去噪的基本原理

关于小波变换数学推导详见 Wavelet

小波顾名思义就是一个很小的波,其积分大概为0,小波按照形状种类分为六种。小波分解个人觉得类似于傅里叶变换,就是将已有的波分解为很多个可以小的波形。

时间序列去噪采用的较广泛的方法为非线性阈值处理法,其原理是通过小波变换后有用信号的能量集中于少数小波系数上,而白噪声在小波变换域上仍然分散在大量小波系数之上。因而相对来说,有用信号的小波系数值必然大于那些能量分散且幅值较小的噪声的小波系数值。因此,从频谱的幅度上看,有用信号和噪声可以实现分离。该方法主要步骤为:

  1. 选择合适的正交小波基和分解层数j,对含噪信号进行小波变换分解到j层;
  2. 对分解得到的小波系数进行阈值处理,可以使用两种处理方法:硬阈值和软阈值法。

硬阈值法保留较大的小波系数并将较小的小波系数置零;软阈值法将较小的小波系数置零,而对较大的小波系数向零收缩。根据相关推导证明了软阈值法去噪后的估计信号是原始信号的近似最优估计,并且具有更广泛的适用性。

关于分解层数的问题,根据多分辨率分析理论,高层分解的小波系数对应的是低频部分,而低频部分主要由信号构成。因此分解层次越高,去掉的低频成分越多,去噪效果越明显,但失真度也增大。为保守起见,分解层次不宜太高,最大不超过5层。对波动性更强的序列如CPU-time序列,一般不超过4层。根据我这段时间对线上时间序列监控数据的实践来讲,基于db4小波函数分解到3-4层可以取得不错的效果。

Continue reading