最近对视频编码的一些研究心得

从某知名视频网站下载了一个小视频, 1080P 25帧的, 比特率是2600kbps, 格式为H.264/AVC, 视频长度为5分钟, 才98M的体积. 某天心血来潮想把它转换为H.265/HEVC格式的视频, 试了无数次才发现, 用现有的工具, 转换出来的H.265/HEVC格式的视频, 体积比它大的, 可能还没有它清晰, 体积比它小的, 清晰度就差更多了. 传说中的H.265/HEVC的优势哪里去了?

1, 一些专有名词

Constant QP (CQP)

Constant Quantization Parameter, 恒定量化编码模式, 也称 CQ (constant quantizer)模式, 英文解释为The quantization parameter defines how much information to discard from a given block of pixels (a Macroblock), 此参数控制每个宏块(Macroblock)的压缩量. 此值越大, 表示要丢弃的Macroblock就越多(压缩率越大), 视频体积越小, 同时视频质量越差. 一般是用GPU转码时, 才会有CQP选项. 不建议使用此模式, 原因如下

Setting a fixed QP means that the resulting bitrate will be varying strongly depending on each scene’s complexity, and it will result in rather inefficient encodes for your input video. You may waste space and you have no control of the actual bitrate.

Average Bitrate (ABR)

平均比特率, 这个不多说了. 不建议使用此模式. 老外的分析如下

One of the main x264 developers himself says you should never use it. Why? As the encoder doesn’t know exactly what’s ahead in time, it will have to guess how to reach that bitrate. This means that the rate itself will vary, especially at the beginning of the clip, and at some point reach the target. Especially for HAS-type streaming, this leads to huge quality variations within short segments.

继续阅读

Windows平台iPhone音乐管理软件

Windows平台上好用且免费的iPhone音乐管理软件不多。今天发现这款免费的DearMob iPhone Music Manager。好用,且免费。

优点:

  • 最重要的一点,免费
  • 不依赖iTunes,网上很多类似的软件需要事先安装iTunes,这款不需要
  • 自动转换.flac等不支持的音乐格式为.mp3/.aac格式然后导入,且转换后的专辑封面/tag等信息均在
  • 界面上可以编辑音乐文件的tag信息

下载地址
https://www.5kplayer.com/iphone-manager/iphone-music-transfer-guide.htm

特别注意:
1,DearMob iPhone Music Manager 本身是免费的,它是DearMob iPhone Manager的其中一个组件。但是DearMob iPhone Manager是收费的,所以下载的时候,需要特别注意,我们要下载的是DearMob iPhone Music Manager,而不是DearMob iPhone Manager。
2,该厂商还提供一个免费的DearMob iPhone Photo Manager,同样是免费的,且是DearMob iPhone Manager的一个免费组件。介绍页面上显示该软件可以把PC上的照片重新拷贝回iPhone中,未尝试。

logstash的drop过滤器插件

logstash在filter段对日志进行解析的时候, 可以直接筛选出我们想要的日志内容, 如果日志内容里不包括某些字段, 我们可以把整条日志直接扔掉, 下面是配置.

input {
    kafka {
        bootstrap_servers => "k1.zhukun.net:6687 k2.zhukun.net:6687"
        #topics_pattern => "zhukun.net.log.rms-api.*"  # 如果收取多个kafaka topic里的消息可以用此写法
        topics => ["zhukun.net_console.log"]
        group_id => "logstash-mp-ops"
        consumer_threads => 10
        decorate_events => true
        auto_offset_reset => "latest"
    }
}

filter {

    # 如果message里不以2019/2020/2021开头, 则直接丢弃整条日志
    if [message] !~ /^[2020|2021|2019]/ {
        drop { }
    }
	
    # 直接打印出来原始日志看看
    #ruby {
    #    code => 'puts event("message")'
    #}
	
    # grop正则匹配
    grok {
        match => { "message" => '%{TIMESTAMP_ISO8601:time_local}\s*\[%{DATA:service}\]\s*%{LOGLEVEL:loglevel}\s*%{DATA:message}$' }
        overwrite => ["message"]
    }

    # 日期处理
    date {
        # 将time_local赋给@timestamp字段, 右侧是time_local的实际格式, 例如2019-03-18 08:12:45.006
        match => ["time_local", "yyyy-MM-dd HH:mm:ss.SSS"]
        target => "@timestamp"    # 默认target就是@timestamp
    }

    # 如果把整条日志都解析出来以后(已经解析到各个tag之中), 原始日志应该也没什么用了, 可以考虑直接扔掉原始日志
    #mutate {
    #    remove_field => [ "message" ]
    #}

}

output {
    elasticsearch {
        hosts => ["10.18.4.24:9200","10.18.4.25:9200","10.18.4.77:9200","10.18.4.78:9200", "10.11.149.69:9200","10.16.22.149:9200"]
        index => "zhukun.net_console.log-%{+yyyy.MM.dd}"
    }
    #stdout {
    #   codec => rubydebug {
    #       metadata => true
    #    }
    #}
}
继续阅读

使用Grafana的Templates功能实现主机分组

有时候,Grafana里展示的主机太多了,我们可能需要将主机进行分组展示,例如把主机根据使用的项目分组,或者按照使用部门进行分组。这个时候,就需要用到Grafana的Templates(模板)功能了。实际效果见下图:

使用Grafana的Templates功能实现主机分组

首先,我们看看Prometheus的配置文件:

继续阅读

WordPress post from xmlrpc

从Wordpress 3.5版本开始, xmlrpc默认开启, 更早期的版本可能在设置中手动开启. 以下是一个通过xmlrpc发布文章的脚本(python版本):

vim post.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

import datetime, xmlrpclib

wp_url = "http://www.example.net/xmlrpc.php"
wp_username = "USER"
wp_password = "passwd"
wp_blogid = ""
status_draft = 0
status_published = 1

server = xmlrpclib.ServerProxy(wp_url)

title = "article title"
content = "article content"
#date_created = xmlrpclib.DateTime(datetime.datetime.strptime("2011-10-20 21:08", "%Y-%m-%d %H:%M"))
categories = ["Beijing"]
tags = ["sometag", "othertag"]
data = {'title': title, 'description': content, 'categories': categories, 'mt_keywords': tags}

post_id = server.metaWeblog.newPost(wp_blogid, wp_username, wp_password, data, status_published)

请注意: 如果脚本里的categories不存在, 则会把文章post到默认分为中.

systemd service log check

systemd服务一般使用systemctl命令来启动, 那么如果服务启动不正常, 如何查看它的日志呢?

journalctl -u myapp.service

如果想查看实时日志输出( follow logs in real time ), 可以加一个-f参数:

journalctl -u -f myapp.service

另外2个有用的参数:

-e          直接打印到日志末尾;
--no-pager  打印全部日志(无需再翻页).

其实systemctl也是可以直接查看日志的:

systemctl -l status myapp.service

ansible use timestamp as vars

ansible 使用时间戳作为变量

- hosts: app_group
  remote_user: root
  gather_facts: yes    # 需要设定为yes(也可以省略),不然会提示ansible_date_time' is undefined
  vars:
    - VERSION:  v1.0.0
    - GIT_APP_NAME: HelloWorld
    - GIT_ADDR: git@github.com/yourname/helloworld.git
    - LOCAL_CODE_DIR: '/opt/ansible/yourname/code'
    - CMD_TIME: "{{ ansible_date_time.iso8601_basic_short }}"    # 获取系统时间戳
  tasks:

    - name: sync code to build server
      synchronize:
        src: "{{ LOCAL_CODE_DIR }}/{{ GIT_APP_NAME }}/" 
        dest: "/opt/src-{{ VERSION }}-{{ CMD_TIME }}"

    - name: 编译
      shell: "cd /opt/src-{{ VERSION }}-{{ CMD_TIME }}; make clean && make -j12;"

    - name: 同步新版本文件到本地
      synchronize
        src: "/opt/src-{{ VERSION }}-{{ CMD_TIME }}/helloworld"
        dest: "{{ LOCAL_CODE_DIR }}/helloworld_online/"
        mode: pull

    - name: 同步新版本文件到线上
      synchronize:
        src: "{{ LOCAL_CODE_DIR }}/helloworld_online/helloworld"
        dest: "/opt/helloworld/helloworld"

    - name: 计算线上md5值
      shell: "md5sum /opt/helloworld/helloworld |awk '{print $1}'"
      register: helloworld_online

    - name: 计算本地md5值
      shell: "md5sum {{ LOCAL_CODE_DIR }}/helloworld_online/helloworld | awk '{print $1}'"
      register: helloworld_local
      connection: local    # 表示在本地执行相关命令

    - name: md5 check
      debug:
        msg: 'remote: {{ helloworld_online.stdout }} local: {{ helloworld_local.stdout }}'

    - name: 本地与线上md5值对比成功重启服务(随机sleep 5秒,确保服务可用率)
      when: helloworld_online.stdout == helloworld_local.stdout
      shell: "sleep $((RANDOM % 5)) && cd /opt/helloworld/ && sh ./start.sh"
      args:
        executable: /bin/bash