出家如初,成佛有余

使用docker来实现libreoffice并发转换docx文件为pdf

Posted in Uncategorized by chuanliang on 2017/06/08

由于libreoffice的soffice不支持多进程,只允许同时有一个进程来转换docx文件为pdf文件,因此无法多线程并发执行转换操作。

为实现并发转换操作,有两种方案:

方案一:将转换代码部署到不同的服务器上,此种方案需要单独服务器,对资源要求较高,部署也麻烦;

方案二:利用docker对资源的隔离特性,把libreoffice 放到docker中,然后启用多个libreoffice容器,java代码调用不同容器的soffice命令来并发转换docx文件。

1、安装docker相关程序

CentOS7已经缺省支持docker

yum install docker

service docker start

chkconfig docker on

简单的安装使用可以参考 https://linux.cn/article-4340-1.html

2、把缺省的docker镜像仓库换成国内的网易镜像

echo "DOCKER_OPTS=\"\$DOCKER_OPTS –registry-mirror=http://hub-mirror.c.163.com\"" >> /etc/default/docker

service docker restart

3、下载centos docker镜像

docker pull centos

4、启动centos的docker镜像

docker run -it centos /bin/bash

5、进入docker容器

docker run -it centos -v /root/install:/root/install  /bin/bash

由于生产镜像时候,可能需要与宿主主机共享一些文件,例如中文ttf文件,因此在run 时候使用了-v参数,用于宿主主机与docker container之间的共享目录。

假设docker 容器与宿主机的共享目录为/root/install 。

Docker容器和主机之间共享数据,可以参考 https://www.howtoing.com/how-to-share-data-between-the-docker-container-and-the-host/

6、安装libreoffice、中文字体库等所需的软件

yum install libreoffice-writer.x86_64

yum groupinstall "Fonts"

yum groupinstall "Input Methods"

7、生成安装了libreoffice、中文字体等软件的docker 镜像

docker commit CONTAINER_ID liang/libreoffice1

其中:

CONTAINER_ID是docker ps -a得到了容器id docker ps -a|grep "centos"|awk ‘{print $1}’

liang/libreoffice1 是我们生成的docker镜像

8、停掉刚才启动的centos容器

docker stop CONTAINER_ID

9、启动我们新生成的docker 镜像

根据并发转换docx为pdf文件的需要,基于我们自己生成的docker镜像,启动多个docker的容器,利用docker容器对资源的隔离,调用不同容器中的soffice来并发处理不同的pdf文件

docker run –name office1 -it -d -v /root/pdf1:/root/pdf1  liang/libreoffice1

docker run –name office2 -it -d -v /root/pdf1:/root/pdf1  liang/libreoffice1

镜像文件与宿主机的共享目录为/root/pdf1和/root/pdf2,在共享目录中放入要转换的docx文件

docker exec -it office1 /bin/bash

 

10、调用soffice命令行,将docx转为pdf

docker exec -it office1 /bin/soffice –headless  –invisible –norestore –nodefault –nolockcheck  –nofirststartwizard –convert-to pdf:writer_pdf_Export –outdir /root/pdf1 /root/pdf1/liang1.docx

docker exec -it office2 /bin/soffice –headless  –invisible –norestore –nodefault –nolockcheck  –nofirststartwizard –convert-to pdf:writer_pdf_Export –outdir /root/pdf2 /root/pdf2/liang2.docx

以上命令行放到java代码中,同时可以在多个线程中并发调用。

佛教和基督教是根本对立无法互相包容的吗?

Posted in Uncategorized by chuanliang on 2014/05/05

我在知乎就《佛教和基督教是根本对立无法互相包容的吗?》做的回答。

如果只是单纯根据“圣经”、“金刚经”等基督教、佛教的传统经典字面解读的话,基督教和佛教教义上确实有诸多不相容的地方,上面各个楼层已经对此有解读。
但根据个人修炼经历,我更倾向于:所有宗教最高层面都是殊途同归的,都归于“一体意识”。因此从所有宗教的本质来看,各个宗教间并没有冲突之说。不管是《圣经》、《金刚经》等宗教经典还是教义都是历代人解读传承下来的,既然是解读,那肯定掺杂了私货。其实教义并不重要,重要的是探究教义后面的本质,“知我说法,如筏喻者,法尚应舍,何况非法”。看一些基督教图书,例如提姆.陶乐的《诸神的面具》、《一掷千金的上帝》最大感受就是:原来这么常见的宗教故事都被误读了,这么常见的故事后面还有如此深奥的道理。
不 管是基督教、佛教、伊斯兰教等宗教本质上都是要回答: “我是谁?”这个核心问题,由此衍生了各个宗教不同的世界观、方法论等。但从本质上来说,所有宗教最高层面都认为:“小我”/”我执”思维中根深蒂固的的 “二元意识”(好与坏、丑与美等等)是所有问题的根源,解决之道在于一体意识,认识到:你既是佛、你与神一体、你本具足圆满。
以上观点是个人从修炼角度来看的,本人并非佛教/基督教研究专业人士。更专业的解读,强烈推荐有兴趣的同学看看肯.威尔伯的《意识光谱》、《没有疆界》,个人觉得对此讲解得极为精辟,个人也比较接受其观点。
说 一下我自己的修炼经历:一直并没有明确的信仰,因此在修炼过程中,对基督教、佛教并没有排斥心理,秉持:只要能够帮助自己修炼都值得一试。因此对基督教体 系的各种图书:《圣经》、《奇迹课程》(包括《告别娑婆》、《耶稣的禅意》等)、《与神对话系列》、提姆.陶乐的《诸神的面具》、《一掷千金的上帝》等 书;对佛教/禅宗体系的《金刚经》/《心经》等经典、《一行禅师系列图书》、《圣严法师系列图书》、《南怀瑾系列》等都有仔细研读,当然也包括像肯.威尔 伯、克里希那穆提等。最终形成了上述观点(当然除了看书外,还通过跑步等肉体锻炼,打坐静心)。关于修炼,以前给团队分享过一篇《调心》,供参考。

Tagged with: ,

知乎问答:微信发红包之后,腾讯应该用什么方法进一步推动用户使用微信的支付系统?

Posted in Uncategorized by chuanliang on 2014/02/23

http://www.zhihu.com/question/22620813/answer/22022381

从微信红包、打车、自媒体付费等微信支付重点树立的标杆、力推的应用场景可以看出:目前微信团队对微信支付的定位是:小额支付+偏实名(与虚拟交易对应)+交易风险低的场景。
小 额支付、交易风险低相对好理解,值得注意和强调的是:偏实名。微信支付目前采用的方式是:只支持与银行卡绑定,不支持常见的账户支付、虚拟币支付。通过银 行卡账户体系的实名体系来保证实名和规避风险。之所以这样选择,原因有诸多,最核心的原因在于:移动支付尚处于初期摸索阶段,有诸多不确定的风险(交易风 险、运营 风险、政策风险等等),小心谨慎为上。
回到题主的问题,个人觉得微信团队下一步:
1、树立更多的微信支付的经典应用场景
由于没有盈利压力,微信支付应该还是以树立行业应用标杆稳扎稳打方式铺开。在场景选择上应该还是会秉持以上的定位,因此大家提到的微信支付诸多生活支付的场景应该不会一下大规模放开。
目 前微信支付在行业应用场景选择上还是比较封闭、不透明的,基本以自己选择场景为主方式。其实在应用场景选择上,微信支付可以开放透明些,相对于自上而下的 创造场景,发挥广大用户、商家的想象力,肯定有诸多更有趣、更经典的应用场景出现。典型的例子就是微信红包+AA收款被群众演变成扎金花。
2、继续普及银行卡支付,逐步引入账户支付
银行卡绑定支付 VS. 账户支付/虚拟币支付
使用银行卡绑定的方式意味着微信支付的目标群体仍然局限于有在线支付使用习惯的用户群体,对那些没有银行卡或没有使用在线支付习惯的人群来说,账户支付以及虚拟币支付是这类人群经常选择的支付方式,而这类人群很大程度集中在游戏等虚拟业务上。
或许有人会说,微信支付的目标人群不是这部分人,不反驳、不细说,只能说:千万不要小看这部分群体的消费能力和用户数。而且腾讯最赚钱的业务和大家认为微信未来最具想象空间的业务之一是游戏,那么?
因 此从长远来说,要更好支撑微信游戏等业务,微信支付肯定会支撑账户支付,原因包括银行通道交易手续费、便捷性等等。当然应该不会是下一步微信支付的重点, 微信团队目前的重点应该还是培养用户使用移动支付的习惯,从这这一点来说,支付宝“现金是我们最大的竞争对手”的说法同样可以适用于微信支付上。
3、继续完善微信支付的基础设施
由于目前应用场景主要集中在小额、偏实名、交易风险低的场合,要真正大规模展开,微信支付(乃至财付通)的支付体系的基础设施还是偏弱的,尤其是适合移动支付的风控系统、账户体系等建设。

一个任务调度分发服务的架构

Posted in Uncategorized by chuanliang on 2013/11/10

项目需要实现在多台服务器间做任务、账号资源、服务器资源的分布式调度、分发,需求场景不细说,你懂的。先考察了Celery、resque、Pyres 几个典型的异步任务调度的开源项目,对比项目需求后,感觉要直接利用这几个项目做实现,比较费劲,基于django、redis、rabbitmq、 APScheduler实现了自己的分布式任务分发调度器,效果不错,架构供参考。

一些体会:

1、习惯了关系型数据库导向的设计思维方式,一下切换到Redis上,在数据结构的设计上需要在思维模式上做一些适应、调整。习惯后,会深深体会到其优势。Redis提供的几种数据结构貌似简单,但能够满足诸多复杂的场景,而且对数据结构的定义、调整极其方便。

2、有诸多基于Redis的消息队列的项目可供选择,之所以没采用Redis作为分布式的消息队列,而采用了RabbitMQ ,主要是考虑到消息的可靠传输、消息确认、消息路由问题。

3、任务队列的概念,在诸多业务架构设计中都应该引入,对有架构扩展、性能都极为重要。对一般的任务调度服务,没必要自己再发明一遍轮子,建议先考察一下Celery或resque后,再考虑是否需要自己实现。

4、之所以有任务拆分的逻辑,主要考虑:分拆成相互独立的子任务,以便于尽快执行任务,同时避免任务过长失败的几率

使用Nginx Upload Module及pycurl来实现大文件断点上传

Posted in Uncategorized by chuanliang on 2013/03/22

由于项目需要,需要实现超大文件的上传,且要考虑上传请求的负载均衡、客户端往服务器的断点续传(上行)、服务器可扩展性等需求。对比ftp、自定 义Socket协议、php等服务器脚本实现上传功能后,选择了基于Ngnix Upload Module+pycurl来实现大文件的上传。

技术方案图_cr

1、 nginx、nginx upload module、nginx upload progress module安装
mkdir ~/nginx-source
cd ~/nginx-source
wget http://nginx.org/download/nginx-1.2.7.tar.gz
tar zxvf nginx-1.2.7.tar.gz
wget http://www.grid.net.ru/nginx/download/nginx_upload_module-2.2.0.tar.gz
tar zxvf nginx_upload_module-2.2.0.tar.gz
wget -O nginx-upload-progress-module-master.zip https://github.com/masterzen/nginx-upload-progress-module/archive/master.zip
unzip nginx-upload-progress-module-master.zip
cd nginx-1.2.7
./configure –user=daemon –group=daemon –prefix=/usr/local/nginx-1.2.7/ –add-module=../nginx_upload_module-2.2.0 –add-module=../nginx-upload-progress-module-master –with-http_stub_status_module –with-http_ssl_module –with-http_sub_module –with-md5=/usr/lib –with-sha1=/usr/lib –with-http_gzip_static_module
make
make install

2、 php安装
mkdir ~/php-source
cd ~/php-source
wget http://www.php.net/get/php-5.4.13.tar.gz/from/cn2.php.net/mirror
tar zxvf php-5.4.13.tar.gz
./configure –prefix=/usr/local –with-config-file-path=/etc –enable-suhosin –enable-fpm –enable-fastcgi –enable-force-cgi-redirect –disable-rpath –enable-discard-path –with-mysql –with-mysqli –with-sqlite –with-pdo-sqlite –with-iconv-dir=/usr/local –with-freetype-dir –with-jpeg-dir –with-png-dir –with-gd –with-zlib –with-libxml-dir –with-curl –with-curlwrappers –with-openssl –with-mhash –with-xmlrpc –with-mcrypt –with-ldap –with-ldap-sasl –enable-xml –enable-safe-mode –enable-bcmath –enable-shmop –enable-sysvsem –enable-inline-optimization –enable-mbregex –enable-mbstring –enable-gd-native-ttf –enable-ftp –with-bz2 –enable-pcntl –enable-sockets –enable-zip –enable-soap –enable-pdo –disable-debug –disable-ipv6
3、 nginx配置

user daemon;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;

#log_format main ‘$remote_addr – $remote_user [$time_local] “$request” ‘
# ‘$status $body_bytes_sent “$http_referer” ‘
# ‘”$http_user_agent” “$http_x_forwarded_for”‘;

#access_log logs/access.log main;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;
upstream web{
server 127.0.0.1:80;
}
upstream php{
server 127.0.0.1:9000 max_fails=0;
}

server {
listen 80;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;
client_max_body_size 100m;
# Upload form should be submitted to this location
location /upload {
# Pass altered request body to this location
root html;
upload_pass /upload.php;

# Store files to this directory
# The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist
upload_store /var/uploads 1;

# Allow uploaded files to be read only by user
upload_store_access user:r;
upload_resumable on;

# Set specified fields in request body
upload_set_form_field “${upload_field_name}_name” $upload_file_name;
upload_set_form_field “${upload_field_name}_content_type” $upload_content_type;
upload_set_form_field “${upload_field_name}_path” $upload_tmp_path;

# Inform backend about hash and size of a file
upload_aggregate_form_field “${upload_field_name}_md5″ $upload_file_md5;
upload_aggregate_form_field “${upload_field_name}_size” $upload_file_size;

upload_pass_form_field “^submit$|^description$”;
}

#error_page 404 /404.html;
error_page 405 =200 @405;
location @405
{
root html;
}

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
location ~ .*\.php(\/.*)*$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

}

}

创建上传目录
mkdir -p /var/uploads/{0..9}
mkdir -p /var/uploads/{a..z}
chown -R daemon:daemon /var/uploads

启动
/usr/local/nginx-1.2.7/sbin/nginx
/usr/local/sbin/php-fpm

4、 在document root 目录html下创建upload.html和upload.php
upload.html

Select files to upload

 

upload.php

 

5、 测试
页面上传测试:

http://127.0.0.1/upload.html

使用curl测试文件上传:
curl -v -i -XPOST http://127.0.0.1/upload -F “media=@/home/liangchuan/baby4.jpg;type=image/jpeg;filename=baby4.jpg

使用pycurl脚本测试大文件分段续传(测试了一个90M的文件,每块按照30M传输):
# -*- coding: utf-8 -*-
import pycurl
import StringIO
import os
import math

chunksize=30000000
filename=’/home/liangchuan/test.rar’

class FileReader:
def __init__(self, fp, start, length):
self.fp = fp
self.fp.seek(start)
self.length = length

def read_callback(self, size):
#print ‘read_callback(%d)’ % size
if self.length == 0: # read all
return ”
if self.length > size:
self.length -= size
#print ‘set size = %d’ % size
return self.fp.read(size)
else :
size = self.length
self.length -= size
return self.fp.read(size)

fout = StringIO.StringIO()
filesize = os.path.getsize(filename)

c = pycurl.Curl()
c.setopt(c.URL, ‘http://127.0.0.1/upload’)
pf = [(‘test’, (c.FORM_FILE, filename,c.FORM_CONTENTTYPE,’application/x-rar-compressed’)) ]
c.setopt(c.HTTPPOST, pf)
c.setopt(c.VERBOSE, 1)
num=int(filesize/chunksize)+1
import StringIO
b = StringIO.StringIO()
c.setopt(pycurl.WRITEFUNCTION, b.write)
for i in range(1,num):
c.setopt(pycurl.INFILESIZE, chunksize)
c.setopt(pycurl.READFUNCTION, FileReader(open(filename, ‘rb’), (i-1)*chunksize,chunksize).read_callback)
c.setopt(pycurl.RANGE,’%s-%s’ % ((i-1)*chunksize,i*chunksize))
c.perform()
print b.getvalue()
#response_code = c.getinfo(pycurl.RESPONSE_CODE)
#response_data = fout.getvalue()
#print response_code
#print response_data
c.close()

备注:
1、 上述脚本只是用于测试使用,用于实际的生产场合(例如用于大文件的自动断点传输),在机制上还有需要完善的。大的思路:
服务器端的upload.php通过Redis或数据库等其他机制来存储每块文件上传的状态,并提供查询接口供客户端查询
客户端使用sqlite来维护每块文件的传输状态,失败后,先调用服务器的查询接口查询成功的range值,然后从指定的range值重新发起上传操作

2、 以上pycurl的例子主要是测试后台自动上传功能,如果是基于有Web界面的文件上传,可以参考http://blueimp.github.com/jQuery-File-Upload/

基于HTTP Live Streaming(HLS) 搭建在线点播系统

Posted in Uncategorized by chuanliang on 2012/11/09

1、 为何要使用HTTP Live Streaming

可以参考wikipedia

HTTP Live Streaming(缩写是 HLS)是一个由苹果公司提出的基于HTTP的流媒体 网络传输协议。是苹果公司QuickTime X和iPhone软件系统的一部分。它的工作原理是把整个流分成一个个小的基于HTTP的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。在开始一个流媒体会话时,客户端会下载一个包含元数据的extended M3U (m3u8) playlist文件,用于寻找可用的媒体流。

HLS只请求基本的HTTP报文,与实时传输协议(RTP)不同,HLS可以穿过任何允许HTTP数据通过的防火墙或者代理服务器。它也很容易使用内容分发网络来传输媒体流。

2、 HTTP Live Streaming技术方案

HTTP服务:使用Nginx提供HTTP服务,通过使用nginx-rtmp-module https://github.com/arut/nginx-rtmp-module 来增加对HLS的支持

使用ffmpeg来完成对flv、mp4、mp3等格式的转化

使用ffmpeg或segmenter完成对视频/音频格式文件的切割,切割为m3u8格式及ts文件

3、 准备工作

操作系统CentOS

3.1、准备安装删除已安装包

yum erase ffmpeg x264 x264-devel

3.2、安装各种依赖包

yum install  gcc make nasm pkgconfig wget curl curl-devel zlib-devel openssl-devel perl cpio expat-devel gettext-devel libtool mhash.x86_64 perl-Digest-SHA1.x86_64  pcre.i386 pcre.x86_64 pcre-devel.i386 pcre-devel.x86_64

3.3、安装git

wget -O git-devel.zip https://github.com/msysgit/git/archive/devel.zip

unzip git-devel.zip

cd git-devel/

autoconf

./configure

make

make install

3.4、创建安装包目录

mkdir ~/ffmpeg-source

4、 安装ffmpeg及其依赖包

4.1Yasm

cd ~/ffmpeg-source

wget http://www.tortall.net/projects/yasm/releases/yasm-1.2.0.tar.gz

tar xzvf yasm-1.2.0.tar.gz

cd yasm-1.2.0

./configure

make

make install

4.2x264

cd ~/ffmpeg-source

git clone git://git.videolan.org/x264

cd x264

./configure –enable-shared

make

make install

4.3LAME

cd ~/ffmpeg-source

wget http://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz

tar xzvf lame-3.99.5.tar.gz

cd lame-3.99.5

./configure –enable-nasm

make

make install

4.4libogg

cd ~/ffmpeg-source

wget http://downloads.xiph.org/releases/ogg/libogg-1.3.0.tar.gz

tar xzvf libogg-1.3.0.tar.gz

cd libogg-1.3.0

./configure

make

make install

4.5libvorbis

cd ~/ffmpeg-source

wget http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.3.tar.gz

tar xzvf libvorbis-1.3.3.tar.gz

cd libvorbis-1.3.3

./configure

make

make install

4.6libvpx

cd ~/ffmpeg-source

git clone http://git.chromium.org/webm/libvpx.git

cd libvpx

./configure  –enable-shared

make

make install

4.7 FAAD2

cd ~/ffmpeg-source

wget http://downloads.sourceforge.net/project/faac/faad2-src/faad2-2.7/faad2-2.7.tar.gz

tar zxvf faad2-2.7.tar.gz

cd faad2-2.7

./configure

make

make install

4.8FAAC

cd ~/ffmpeg-source

wget http://downloads.sourceforge.net/project/faac/faac-src/faac-1.28/faac-1.28.tar.gz

tar zxvf faac-1.28.tar.gz

cd faac-1.28

./configure

make

make install

4.9Xvid

cd ~/ffmpeg-source

wget http://downloads.xvid.org/downloads/xvidcore-1.3.2.tar.gz

tar zxvf xvidcore-1.3.2.tar.gz

cd xvidcore/build/generic

./configure

make

make install

4.10FFmpeg

cd ~/ffmpeg-source

git clone git://source.ffmpeg.org/ffmpeg

cd ffmpeg

./configure  –enable-version3  –enable-libvpx –enable-libfaac –enable-libmp3lame  –enable-libvorbis –enable-libx264 –enable-libxvid –enable-shared –enable-gpl –enable-postproc –enable-nonfree –enable-avfilter –enable-pthreads

make

make install

ldconfig –v

5、 安装nginxnginx-rtmp-module

mkdir ~/nginx-source

cd  ~/nginx-source

wget http://nginx.org/download/nginx-1.2.4.tar.gz

tar zxvf nginx-1.2.4.tar.gz

wget -O nginx-rtmp-module.zip  https://github.com/arut/nginx-rtmp-module/archive/master.zip

unzip nginx-rtmp-module.zip

wget -O ngx_cache_purge.zip https://github.com/FRiCKLE/ngx_cache_purge/archive/master.zip

unzip ngx_cache_purge.zip

cd nginx-1.2.4

./configure –user=daemon –group=daemon –prefix=/usr/local/nginx-1.2.4/ –add-module=../nginx-rtmp-module-master –add-module=../nginx-rtmp-module-master/hls –add-module=../ngx_cache_purge-master  –with-http_stub_status_module –with-http_ssl_module –with-http_sub_module –with-md5=/usr/lib –with-sha1=/usr/lib –with-http_gzip_static_module

在nginx.conf中增加rtmp模块的相关配置,配置例子

rtmp {

server {

listen 1935;

chunk_size 4000;

# TV mode: one publisher, many subscribers

application mytv {

# enable live streaming

live on;

# record first 1K of stream

record all;

record_path /tmp/av;

record_max_size 1K;

# append current timestamp to each flv

record_unique on;

# publish only from localhost

allow publish 127.0.0.1;

deny publish all;

#allow play all;

}

# Transcoding (ffmpeg needed)

application big {

live on;

# On every pusblished stream run this command (ffmpeg)

# with substitutions: $app/${app}, $name/${name} for application & stream name.

#

# This ffmpeg call receives stream from this application &

# reduces the resolution down to 32×32. The stream is the published to

# ‘small’ application (see below) under the same name.

#

# ffmpeg can do anything with the stream like video/audio

# transcoding, resizing, altering container/codec params etc

#

# Multiple exec lines can be specified.

exec /usr/local/bin/ffmpeg -re -i rtmp://localhost:1935/$app/$name -vcodec flv -acodec copy -s 32×32 -f flv rtmp://localhost:1935/small/${name};

}

application small {

live on;

# Video with reduced resolution comes here from ffmpeg

}

application mypush {

live on;

# Every stream published here

# is automatically pushed to

# these two machines

#push rtmp1.example.com;

#push rtmp2.example.com:1934;

}

application mypull {

live on;

# Pull all streams from remote machine

# and play locally

#pull rtmp://rtmp3.example.com pageUrl=www.example.com/index.html;

}

# video on demand

application vod {

play /var/flvs;

}

application vod2 {

play /var/mp4s;

}

# Many publishers, many subscribers

# no checks, no recording

application videochat {

live on;

# The following notifications receive all

# the session variables as well as

# particular call arguments in HTTP POST

# request

# Make HTTP request & use HTTP retcode

# to decide whether to allow publishing

# from this connection or not

on_publish http://localhost:8080/publish;

# Same with playing

on_play http://localhost:8080/play;

# Publish/play end (repeats on disconnect)

on_done http://localhost:8080/done;

# All above mentioned notifications receive

# standard connect() arguments as well as

# play/publish ones. If any arguments are sent

# with GET-style syntax to play & publish

# these are also included.

# Example URL:

#   rtmp://localhost/myapp/mystream?a=b&c=d

# record 10 video keyframes (no audio) every 2 minutes

record keyframes;

record_path /var/vc;

record_max_frames 10;

record_interval 2m;

# Async notify about an flv recorded

on_record_done http://localhost:8080/record_done;

}

# HLS

# HLS requires libavformat & should be configured as a separate

# NGINX module in addition to nginx-rtmp-module:

# ./configure … –add-module=/path/to/nginx-rtmp-module/hls …

# For HLS to work please create a directory in tmpfs (/tmp/app here)

# for the fragments. The directory contents is served via HTTP (see

# http{} section in config)

#

# Incoming stream must be in H264/AAC/MP3. For iPhones use baseline H264

# profile (see ffmpeg example).

# This example creates RTMP stream from movie ready for HLS:

#

# ffmpeg -loglevel verbose -re -i movie.avi  -vcodec libx264

#    -vprofile baseline -acodec libmp3lame -ar 44100 -ac 1

#    -f flv rtmp://localhost:1935/hls/movie

#

# If you need to transcode live stream use ‘exec’ feature.

#

application hls {

hls on;

hls_path /var/app;

hls_fragment 5s;

}

}

}

# HTTP can be used for accessing RTMP stats

http {

server {

listen      8080;

# This URL provides RTMP statistics in XML

location /stat {

rtmp_stat all;

# Use this stylesheet to view XML as web page

# in browser

rtmp_stat_stylesheet stat.xsl;

}

location /stat.xsl {

# XML stylesheet to view RTMP stats.

# Copy stat.xsl wherever you want

# and put the full directory path here

root /path/to/stat.xsl/;

}

location /hls {

# Serve HLS fragments

alias /var/app;

}

}

}

6、 安装segmenter

svn co http://httpsegmenter.googlecode.com/svn/

cd  svn/trunk

gcc -Wall -g segmenter.c -o segmenter -lavformat -lavcodec -lavutil -std=c99

cp segmenter /usr/bin/

从优酷上下载一个视频文件,假定为baluobu.flv

找个mp3文件,假定为10year.mp3

mkdir /var/flvs /var/mp4s /var/vc /var/app /var/app/10year /var/app/baluobu

使用ffmpeg将测试视频和音频转为mpeg ts格式文件

ffmpeg -i /var/flvs/baluobu.flv  -f mpegts -acodec libmp3lame -ar 48000 -ab 128k -vcodec libx264 -b 96k -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -subq 5 -trellis 1 -refs 1 -coder 0 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 200k -maxrate 96k -bufsize 96k -rc_eq ‘blurCplx^(1-qComp)’ -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect 320:240 -g 30 -async 2 /var/app/baluobu/baluobu.ts

ffmpeg -i /var/flvs/10year.mp3  -f mpegts -acodec libmp3lame -ar 48000 -ab 128k -vcodec libx264 -b 96k -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -subq 5 -trellis 1 -refs 1 -coder 0 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 200k -maxrate 96k -bufsize 96k -rc_eq ‘blurCplx^(1-qComp)’ -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect 320:240 -g 30 -async 2 /var/app/10year/10year.ts

cd /var/app/10year

segmenter -i 10year.ts -d 5 -o 10year -x 10year.m3u8

cd /var/app/baluobu

segmenter -i baluobu.ts -d 5 -o buluobu -x baluobu.m3u8

7、测试

简单起见使用VLC测试。

http://192.168.1.11:8080/hls/10year/10year.m3u8

http://192.168.1.11:8080/hls/baluobu/baluobu.m3u8

如果无问题,说明已经正常配置成功了HTTP Live Streaming(HLS)服务

可以再iOS设备上使用safari访问以上地址

或者在android机器上安装vplayer后访问以上地址

如果需要通过网页形式提供在线视频,需要在nginx的mime.types文件中添加如下MIME类型:

.m3u8 application/x-mpegURL
.ts video/MP2T

同时在HTML5页面中使用video标签包含视频的m3u8文件

<video controls>
<source src=http://192.168.1.11:8080/hls/baluobu/baluobu.m3u8 />
</video>

8、开发说明

iOS已经原生支持HTTP Live Streaming(HLS),只需要使用MPMoviePlayerController播放以上地址即可

apple文档:http://bit.ly/Rnpsef

Android 3.x以后通过新增的NuPlayer类才支持HTTP Live streaming,而且功能也较弱,为简化处理,可以使用

Vitamio     http://vov.io/vitamio/http://code.taobao.org/p/oplayer/src/ 下载

Servestream http://sourceforge.net/projects/servestream/

nginx-rtmp-module 本身也支持RTMP协议,从而也可以基于nginx来搭建在线直播系统。

 

移动互联网时代本地化运营杂思

Posted in Uncategorized by chuanliang on 2012/05/13

  极其好移动互联网时代旅游领域的O2O机会,但旅游领域基本都有巨头凭借互联网上已有的用户、资本、行业及人才积累等优势在全面布局,初创型的公司还有机 会吗?答案是肯定有,对应方法、路径及机会有很多,这在其中个人觉得本地化是创业型公司们有效区隔那些巨头们的重要手段。

    对比一下各种大众点评之类在O2O领域的标杆企业,可以看出:对于一个纯正的互联网公司而言,基于统一平台基础上的平台化研发、平台化运营是其核心的竞争 优势,在统一平台基础上才可能沉淀用户、沉淀内容、吸引流量,从而在规模效应基础上建立起业务模式。因此大部分互联网公司都会围绕统一的平台来展开业务。

    同时由于互联网公司核心的能力之一在于运营能力,因此这些巨头们基于核心利益的考虑,在平台运营上基本为自主运营,但自主运营随之而来的问题是庞大运营团队对应的巨大成本、管理挑战、规模化问题等等。可以看出:在本地化运营上,那些巨头们面临巨大的挑战:

  • 业务主要集中在一二线城市,这样才能满足规模效应的优势。如果像三四线城市拓展,就必须养庞大的运营团队
  • 全平台统一运营,本地只为商户拓展及合作,很难发挥本地资源优势,从而实现本地化深度的运营,而深度的本地化运营始终是那些巨头们不愿意过多涉足的领域
  • 各巨头本地的团队只是一个打工者而已,并不会有太多的人会把工作当成事业来投入

    基于此,对众多的移动互联网创业者而言,在二三四线城市基于本地化运营的O2O其实挺有机会的。

    那么这里所说的本地化包括那些呢?

1、本地化元素

  • 本地化运营
  • 本地化营销
  • 本地化美景
  • 本地化点评
  • 本地化社会化问答
  • 本地化旅游攻略
  • 本地化的导游
  • 本地化的交友
  • 本地化的特产
  • 本地的文化
  • 本地的游记
  • 本地化的广告推送
  • 本地化电子杂志
  • 本地化优惠券
  • 本地化的团购
  • 本地化的移动电子商务
  • 本地化的互动游戏
  • 本地化的离线地图
  • 本地化的新闻、天气等等
  • 本地化的线下合作
  • 基于位置及场景的个性化推荐
  • 等等

2、那些地方站的个人站长们

    在互联网时代一些由个人站长自己搭建并运营的地方站做得风生水起,地方站成功的原因大致可以总结为如下几点:

  • 最接近市场一线,熟悉本地的市场及用户需求,在内容及服务上更能满足当地用户的需求
  • 与当地资源合作最为擅长
  • 基于个人使命和利益驱动的热情,这种热情可以攻克任何艰难险阻,无人可挡

    应该说:各本地站的个人站长是最适合做本地化运营的人群。

    但可以看出,在互联网时代个人站长们其实举步维艰,在移动互联网时代更为严峻。个人站长没落的原因有几个:

  • 缺少持续的产品研发能力和运营能力,无力“满足人民群众日益增长的物质与文化生活的需要”
  • 缺少能够持续提供支持的平台,帮助其不断超越瓶颈
  • 缺少持续的盈利能力,维持艰难
  • 热情的丧失

    传统互联网下有Discuz之类的建站工具(可以也称之为开放平台吧)来帮助降低建站门槛,个人站长只需关注本地化运营即可。在移动互联网时代工具及运营 模式上都有所变化,而且在当前移动互联网相关的研发人才极度缺乏,在资源有限的情况下,大家都将注意力集中于自己产品的研发运营上,在移动互联网时代谁来 提供类似Discuz这样的工具呢?

    谈到本地化运营和开放平台,在互联网时代Discuz是最有机会的,腾讯收购它应该也有此意图,但最终毫无声息,原因有几个:

    1、Discuz定位为纯技术平台而非运营型平台

    2、未建立一种对个人站长们有价值的业务模式,无法参与利益分配

    3、并未在平台运营、营销上为个人站长们提供其他有价值的服务

     在移动互联网时代谁来做移动互联网时代的Discuz呢?相信一定会有公司来承担此角色,如果能吸取Discuz的经验教训,采用开放平台的模式,结合移动互联网及聚焦垂直行业,一定能够开拓出一种全新的业务模式。

3、本地化一些杂思

   注:原本打算成体系把所想的写出来,写到一半,没兴趣了,直接把近期微博上思考的东西汇总贴出来,也算是自己对思路的梳理。说得再多、想得再多,还不如动手就去做。

    本地化是移动互联网应用竞争的焦点,怎样更好满足用户对本地化的需求呢?是采用一个app通吃天下+集中化的运营+本地化数据,还是采用每一个本地化app+本地化的运营+本地化数据模式呢?或许本地化app结合开放平台的思路能够诞生出一些颠覆性的业务模式。

    对O2O类的移动互联网应用,是否应当遵循“面向全局规划设计、本地化运营”的思路?尽管直接面向全国范围的用户及地域提供服务貌似市场巨大,但在模式尚 未验证及完善情况下贸然全面开花,对模式的构建并不利。在产品及技术架构规划设计时候应当考虑全网用户需求,但在运营上应当遵循本地化运营思路。

    对众多的个人站长而言,要做好本地化运营,有一个类似联盟的组织或商业公司还是有价值的,可以弥补个人站长单打独斗所面临的各种困境,核心在于利益分配及 平台所能提供的价值。平台价值的典型例子为:产品的集中采购、各地方站分销。为何以前那些做地方站整合的最终都失败了呢,值得思考?

    本地化的运营能力决定了产品和服务的品质、品牌,也是规模化的最大挑战。即便像大众点评等也很难做好本地化运营,在局部重要区域可以招聘人来做本地运营,但这些靠薪水驱动的有多少愿意投入全身精力去把繁琐的本地运营做到极致?

    本地化运营最大的挑战不是资金、资源等物质因素,而是缺少对本地化运营充满激情的人,这样的人并非极度匮乏,个人使命+合适的利益结合肯定能找到这样的 人。本地化运营的标杆是那些传统互联网的个人站长们,原因无他:基于个人使命和利益驱动的热情,这种热情可以攻克任何艰难险阻,无人可挡。

    关于开放平台的一些思考 1、平台开放的节奏很重要,在模式尚未验证、标杆尚未建立前就全面开放并非好事 2、开放的心态很重要,但建立公正透明的游戏规则更为重要 3、用户体验是第一位的 4、平台必须持续能提供核心价值 5、平台与合作伙伴间的双向淘汰机制以及信用体系

    纯技术平台的开放并无太多价值,用户关注的是平台所提供业务带来的核心价值,因此成功的开放平台首先聚焦某点进行业务模式的创新,然后在此基础上笼络更多 的合作伙伴来一起完善业务模式,同时输出相关的运营工具等帮助合作伙伴更好为用户提供服务。旅游+移动互联网+开放平台+本地化运营=?

位置服务中的互动游戏

Posted in Uncategorized by chuanliang on 2010/12/14

    在现有的各种位置服务中SCVNGR的游戏模式相对于Foursquare的Check-IN还是挺有创新的,个人也更看好此种模式。

    SCVNGR的模式简单总结来说就是:商家或用户可以通过平台发布“挑战(Challenge)任务”到指定的位置,用户参与这些互动游戏,过关(Treks)后可以获得商家的奖励(Rewards)。

    SCVNGR对自己的服务有比较简洁的解释:

移动互联网,SCVNGR,位置服务,LBS,互动游戏

  这篇文章Is SCVNGR a better fit than Foursquare for your business model?  对SCVNGR模式总结得不错。

1、位置服务中互动游戏的价值

    对于商家而言,在位置服务中提供互动游戏的价值

  • 客户关系维系:拓宽了商家与用户互动形式,避免了传统的购买-服务的单向服务形式,更容易调动用户参与的热情,同时对奖励可以采用积分、电子优惠券、会员卡、勋章等方式,强化用户的忠诚度。
  • 体验营销:让用户在游戏过程中体验产品或服务,这样用户印象更加深刻
  • 更多样化的营销手段:挖宝、开箱子、抽奖、竞猜、秒杀等,而不单纯只是打折优惠
  • 社会化营销:对好玩的游戏,用户会主动通过Facebook、Twitter、Blog等方式传播出去,实际上帮助商家做社会化媒体的营销

对于用户而言,参与商户提供的互动游戏的价值:

  • 消磨无聊的时间,例如在等人时候玩玩在线小游戏
  • 挣积分/优惠券/勋章/排行榜单排名等
  • 与商家互动
  • 了解周边流行的元素

  相比较而言,对商家而言,SCVNGR的模式比Foursquare模式更有吸引力。

2、基于位置服务的互动游戏

    当前SCVNGR所提供的所谓游戏还相当简单,主要还局限于问答、拍照、猜迷、扫描二维QR码等方面,叫“挑战任务”比较恰当,对于真正意义上的互动游戏支持还较弱。相信未来SCVNGR会强化此方面的内容。

    相对于普通的手机游戏,一个好的基于位置服务的互动游戏应当具备如下特征:

  • 与商家服务紧密结合
  • 简单、弱智、好玩,具有较强的互动性、娱乐性
  • 在线形式,游戏本身不需要单独下载安装  

    由于像SCVNGR这样的基于位置服务的互动游戏必须联网才有价值,而各手机操作系统对Flash的支持情况的差异,指望采用传统Web网页游戏的Flash模式行不通。目前想到两种方案:

    1)、客户端内置游戏引擎,联网动态解析服务器端商家设定的游戏。

    2)、未来iphone、android对html5的支持都还不错,以html5方式提供互动游戏倒是一种不错的方式。

3、SCVNGR游戏平台的演进

   比较感兴趣的是SCVNGR对自身的定位的描述:

      SCVNGR is a game.

      SCVNGR is a game platform.

      SCVNGR is the game layer on top of the world.

      SCVNGR is constantly evolving.

    在初期尚不具备市场影响力时候,指望通过所谓的开放平台战略来吸引第三方的开发者可能性为零,这此阶段是应用制胜。作为服务提供商应当集中力量自己做几个标杆应用来吸引人气,此时侯SCVNGR扮演了游戏服务提供商的角色。

    有点名气后,要进一步做大,游戏的丰富性、针对性成为平台迈向更大成功的关键因素,尤其是互动游戏的内容能够与商家的服务紧密结合。这单纯依靠SCVNGR这样的服务提供商就无能为力,毕竟SCVNGR自身的资源也有限,对于不同行业的需求并不能深入了解,与此对应的产品创新的能力有限。此时侯SCVNGR将自己的游戏平台进行开放是最佳的选择。相信SCVNGR如果能够做大,最后他会弄个app store或游戏交易市场出来,将商家和第三方开发者串接起来。

   与此同时,SCVNGR鼓励用户、商家在自己的平台上利用已有的应用或从头构建自己的Challenge游戏,这样激活商家、用户这部分群体的活跃度。

   在此基础上平台持续演进、进化。

 

文本挖掘(Text Mining)技术基础

Posted in Uncategorized by chuanliang on 2010/10/30

基于lucene实现自己的推荐引擎

Posted in Uncategorized by chuanliang on 2010/09/30

    采用基于数据挖掘的算法来实现推荐引擎是各大电子商务网站、SNS社区最为常用的方法,推荐引擎常用的Content-Based推荐算法及协同过滤算法(Item-Based 、User-based)在电子商务推荐系统入门v2.0 电子商务推荐系统入门基础  中已经有所阐述。但从实际应用来看,对于大部分中小型企业来说,要在电子商务系统完整采用以上算法有很大的难度。

1、常用推荐引擎算法问题

  1)、相对成熟、完整、现成的开源解决方案较少

       粗略分来,目前与数据挖掘及推荐引擎相关的开源项目主要有如下几类:

       数据挖掘相关:主要包括WekaR-ProjectKnimeRapidMinerOrange

       文本挖掘相关:主要包括OpenNLPLingPipeFreeLingGATE 等,具体可以参考LingPipe’s Competition

       推荐引擎相关:主要包括Apache MahoutDuine frameworkSingular Value Decomposition (SVD) ,其他包可以参考Open Source Collaborative Filtering Written in Java

       搜索引擎相关:Lucene、Solr、Sphinx、Hibernate Search等

   2)、常用推荐引擎算法相对复杂,入门门槛较低

   3)、常用推荐引擎算法性能较低,并不适合海量数据挖掘

       以上这些包或算法,除了Lucene/Sor相对成熟外,大部分都还处于学术研究使用,并不能直接应用于互联网大规模的数据挖掘及推荐引擎引擎使用。

2、采用Lucene实现推荐引擎的优势

     对很多众多的中小型网站而言,由于开发能力有限,如果有能够集成了搜索、推荐一体化的解决方案,这样的方案肯定大受欢迎。采用Lucene来实现推荐引擎具有如下优势:

    1)、Lucene 入门门槛较低,大部分网站的站内搜索都采用了Lucene

    2)、相对于协同过滤算法,Lucene性能较高

    3)、Lucene对Text Mining、相似度计算等相关算法有很多现成方案

   在开源的项目中,Mahout或者Duine Framework用于推荐引擎是相对完整的方案,尤其是Mahout 核心利用了Lucene,因此其架构很值得借鉴。只不过Mahout目前功能还不是很完整,直接用其实现电子商务网站的推荐引擎尚不是很成熟。只不过从Mahout实现可以看出采用Lucene实现推荐引擎是一种可行方案。

3、采用Lucene实现推荐引擎需要解决的核心问题

   Lucene擅长Text Mining较为擅长,Lucene在contrib包中提供了MoreLikeThis功能,可以较为容易实现Content-Based的推荐,但对于涉及用户协同过滤行为的结果(所谓的Relevance Feedback),Lucene目前并没有好的解决方案。需要在Lucene中内容相似算法中加入用户协同过滤行为对因素,将用户协同过滤行为结果转化为Lucene所支持的模型。

4、推荐引擎的数据源

    电子商务网站与推荐引擎相关典型的行为:

  • 购买本商品的顾客还买过
  • 浏览本商品的顾客还看过
  • 浏览更多类似商品
  • 喜欢此商品的人还喜欢
  • 用户对此商品的平均打分

    因此基于Lucene实现推荐引擎主要要处理如下两大类的数据

   1)、内容相似度

      例如:商品名称、作者/译者/制造商、商品类别、简介、评论、用户标签、系统标签

   2)、用户协同行为相似度

      例如:打标签、购买商品、点击流、搜索、推荐、收藏、打分、写评论、问答、页面停留时间、所在群组等等

5、实现方案

5.1、内容相似度

    基于Lucene MoreLikeThis实现即可。

5.1、对用户协同行为的处理

    1)、用户每一次协同行为都使用lucene来进行索引,每次行为一条记录

    2)、索引记录中包含如下重要信息:

        商品名、商品id、商品类别、商品简介、标签等重要特征值、用户关联行为的其他商品的特征元素、商品缩略图地址、协同行为类型(购买、点击、收藏、评分等)、Boost值(各协同行为在setBoost时候的权重值)

    3)、对评分、收藏、点击等协同行为以商品特征值(标签、标题、概要信息)来表征

    4)、不同的协同行为类型(例如购买、评分、点击)设置不同的值setBoost

    5)、搜索时候采用Lucene MoreLikeThis算法,将用户协同转化为内容相似度

    以上方案只是基于Lucene来实现推荐引擎最为简单的实现方案,方案的准确度及细化方案以后再细说。

    更为精细的实现,可以参考Mahout的算法实现来优化。