大概是从去年年初开始认真的写作。怎奈认真的写作有如雕刻,每次写作少则四五个小时,多则十几个小时,极耗体力,因此再不敢轻易提笔。两周前的一篇文章,更是在机缘巧合之下将鄙人推向了舆论的风口浪尖,至今想起来依然心有余悸。写的人累,想必读的人应该也不会太轻松。值此新春佳节,特奉上一篇“技术小品文”,奢望读者百忙之中施舍一笑。^_^

想象一下,如果把一整部电影压缩成一张图片,那会是怎样壮观的场景?有点迫不急待?看看这里,梯子在这里

是不是想动手尝试下了?可是有这样的软件吗?我没找到。于是唯一的办法就是自己动手,丰衣足食了。代码在这里,依赖 Linux/FFmpeg/bc/GraphicsMagick。运行过程中需要保证 5G 以上的可用磁盘空间。转换耗时约 30 分钟,视电影时长而定。

#!/usr/bin/env bash

################################################################################
# Usage:    A script to convert a movie to a movebarcode
# Author:   Xiao Hanyu
# Depends:
#   ffmpeg:     get basic info of a movie and convert it to a series of images
#   graphicsmagick:
#               convert, mogrify, blur images
#   bc:         shell calculator
################################################################################

function get_duration
{
    ## [0-9]{2}:[0-9]{2}:[0-9]{2}(|\.[0-9]{1,2}) matches:
    ##      hh:mm:ss.ms
    ##      hh:mm:ss
    duration=$(ffmpeg -i $1 2>&1 | grep 'Duration' | grep -E -o "[0-9]{2}:[0-9]{2}:[0-9]{2}(|\.[0-9]{1,2})")
    duration_h=$(echo $duration | awk -F: '{print $1}')
    duration_m=$(echo $duration | awk -F: '{print $2}')
    duration_s=$(echo $duration | awk -F: '{print $3}')
    movie_seconds=$(echo "$duration_h * 3600 + $duration_m * 60 + $duration_s" | bc)
}

function get_fps
{
    fps=$(ffmpeg -i $1 2>&1 | grep -E -o "[0-9]{2}\.[0-9]{2}\ fps" | grep -E -o "[0-9]{2}\.[0-9]{2}")
}

movie=$1

get_fps $movie
get_duration $movie

## use multi-cores of cpu to improve the speed of ffmpeg, see ffmpeg man page
cpu_cores=$(cat /proc/cpuinfo | grep processor | wc -l)

time ffmpeg -i $1 -r 1 -threads $cpu_cores image%d.png
time gm mogrify -resize 0.5%x100% *png
time gm convert $(for i in `seq 1 $movie_seconds`; do ls -l image$i.png; done | awk '{print $9}') +append result1.png
time gm convert result1.png -blur 50 result2.png

# resize result2.png with a proper size
# I set new width to 2000, while keep the height intact
new_width=2000
new_geometry=$(gm identify  result2.png | awk '{print $3}' | awk -F+ '{print $1}' | sed 's/[0-9]*x/2000x/g' | sed 's/$/!/g')
gm convert -resize $new_geometry result2.png result3.png

rm image*png

if [ -e $(which xdg-open) ]; then
    xdg-open result3.png
fi

代码逻辑很少,先是通过 FFmpeg 进行截图,然后用 GraphicsMagick 进行图片的接合、缩放和模糊处理,最后清扫战场,删除一些临时文件,就这么简单。最后,奉上《迁徙的鸟》 和《阿甘正传》的条形码,博君一笑。