[教程]树莓派上的Badapple 精华

14205浏览
查看: 14205|回复: 17

[教程] 树莓派上的Badapple

[复制链接]
熟悉二次元的朋友对于Badapple一定不会陌生,基于它本身的黑白手绘风格,被大量技术宅广泛演绎在各种屏幕上
有屏幕的地方就有BadApple
本篇教程的重点并不在于代码,而在于解决这个问题的思路,假如只是纠结于这个项目本身的话,就不能理解到通用的其它屏幕显示的方法了。

我们的最终目标是在Nokia5110屏幕上用树莓派驱动来完整显示这个视频。


先来看一下效果
首先我们知道,对于Nokia5110而言,直接在树莓派写一个驱动,使它能够像外接hdmi显示屏一样流畅显示这样的难度显然比较大,反正我没什么思路。

那么退而求其次,我们也能想到,视频是一帧一帧的播放的,假如我们能够用树莓派来显示一张图片,那么当树莓派更换图片显示的速度够快时,就能达到视频的效果

初步整理一下我们需要做哪些工作:
  • 获得BadApple原视频,必须要最超清的
  • 把视频的每一帧分割出来,做成一张一张图片
  • 由于视频的分辨率和nokia5110的分辨率(84x84)不相同,所以需要批量转换
  • 在5110上能够显示一张图片
  • 获得原视频中的音乐,在播放图片的同时播放音乐
  • 编写代码,使得显示图片的速率和原程序的帧率相近,肉眼看起来才能有相似的效果

获得原视频
通过网络搜索,很容易就能找到相关的视频,不过想要找到超清的,还是需要花一番功夫

想要下载看的话,可以直接看这个百度云的文件
链接:http://pan.baidu.com/s/1ntR2MDj
密码:ybsw

分割视频

方法有很多种,我想找个最简单的,发现linux下有命令行工具就直接用了,不过在Ubuntu下没找到。。由于项目要用到树莓派,索性就在树莓派上使用ffmpeg这个命令行工具来从上面的视频中来获得我们需要的每一张帧。
第一步是要把上面的视频上传到树莓派上,可以用SFTP的方式或者简单的U盘复制过去,命令行下运行:
  1. $ ffmpeg -i badapple.mkv example.%d.jpg
复制代码



具体的ffmpeg工具使用方法可以参考这个http://blog.chinaunix.net/uid-72186-id-2657751.html
然后就会有六千多张图片生成,也就是视频播放时的那些帧了,仔细一算六千多除以30帧每秒的帧率,恰巧就是视频的时间长度。
1.PNG


转换图片大小
然而这些图片不能直接使用,我们选择的是超清级别的视频,查看图片的属性就会知道分辨率是1440x1080,但是我们打算使用的Nokia屏幕确是84x84的
假如你要使用其他的屏幕,也很难一下子找到恰好符合屏幕的视频,还好我们有一些图片处理软件,比如PS、美图秀秀,找其中一种就可以批量转换分辨率了,图片稍微会有一些变形,毕竟不是等比例的缩放。

显示图片
2.jpg

用树莓派在nokia屏幕上显示图片,可以参考这个adafruit的教程和他们的python库,使用的是SPI方法。
https://learn.adafruit.com/nokia-5110-3310-lcd-python-library
这个教程比较详细,这里就不重复了。

音乐
音乐也要考虑几个方面,比如时间长度是否和我们需要的一样,毕竟网上版本很多,有长有短很正常;音乐的音效是否足够好。。。
用最简单的方法就是从上面的那个视频里直接提取出音乐了
提取的方法有不少,百度一下一般就能解决,这里也不详述了。
用python语言播放音乐有很多种方法,这里我用了以前用过的一种,通过pygame库来播放。
使用时只需要这样就能播放badapple.flac的音乐了
  1. import pygame
  2. pygame.init()
  3. pygame.mixer.init()
  4. pygame.mixer.music.load("badapple.flac")
  5. pygame.mixer.music.play()
复制代码


像视频一样播放图片
这是这份教程的难度所在啊。。建议你先不看下面,自己想一想,反正我试了好几次才想到这个办法

一开始我想偷懒,同时以为树莓派性能不会太强,就索性让音乐开始之后,直接开始显示图片,用一个while循环不停歇地显示下一张图片,一次性显示完6571张。

结果发现树莓派还是比较给力的。。在音乐结束前就播放完图片了。。

于是我就想,既然速度这么快,那么我在图片显示的间隔里加几毫秒是不是就行了,于是在while循环里每一次显示完图片就sleep几毫秒。

结果发现很难正好凑到音乐结束

仔细考虑一下,显示图片的速度本身是不可控的,和树莓派当时的环境温度啊自己的CPU使用情况啊都会有关。。每次凑当然结果会不一样

终于我想到了,只有时间是几乎完全确定的,假如我们从音乐开始播放就计时
  1. t = time.time()
复制代码
那么,while循环显示图片的时候就可以通过帧率30和时间来算出下一次要显示哪一张图片!
  1. count = (int((time.time()-t)*30))+1
复制代码


也就是说假如这次显示图片的过程长了,那么我们就跳过下一帧,假如这次显示图片超级快,那么我们就再显示一次这张图,当作拖一下时间,那么无论怎么变化,最后肯定会和音乐一起结束播放!

代码如下,注释没加,如果需要可以评论出来:
  1. import time
  2. import Adafruit_Nokia_LCD as LCD
  3. import Adafruit_GPIO.SPI as SPI
  4. from PIL import Image
  5. import pygame
  6. # Raspberry Pi hardware SPI config:
  7. DC = 20
  8. RST = 21
  9. SPI_PORT = 0
  10. SPI_DEVICE = 0
  11. # Hardware SPI usage:
  12. disp = LCD.PCD8544(DC, RST, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=4000000))
  13. # Initialize library.
  14. disp.begin(contrast=60)
  15. t = time.time()
  16. count = 1
  17. disp.clear()
  18. disp.display()
  19. pygame.init()
  20. pygame.mixer.init()
  21. pygame.mixer.music.load("badapple.flac")
  22. pygame.mixer.music.play()
  23. while count<6571:
  24.         # Clear display.
  25.         tt = time.time()
  26.         picnum = 'example.'+ str(count)+'.jpg'
  27.         # Load image and convert to 1 bit color.
  28.         image = Image.open(picnum).convert('1')
  29.         # Display image.
  30.         disp.image(image)
  31.         disp.display()
  32.         count = (int((time.time()-t)*30))+1
  33.         print (time.time()-tt)
  34. print 'Press Ctrl-C to quit.'
  35. t = t-time.time()
  36. print t
  37. while True:
  38.         time.sleep(1.0)
复制代码
然后参照上文提到的adafruit的教程连好线,插上音响,运行python代码就可以成功地播放了


用类似的方法就可以在其他的平台和显示屏上愉快地享受BadApple了。










大连林海  初级技神

发表于 2016-2-15 20:03:31

大神 终于出山了
回复

使用道具 举报

吹口琴的钢铁侠  初级技匠
 楼主|

发表于 2016-2-15 21:33:39

回复

使用道具 举报

dsweiliang  初级技神

发表于 2016-2-16 10:31:59

为什么这么多人喜欢这个视频呢?
回复

使用道具 举报

吹口琴的钢铁侠  初级技匠
 楼主|

发表于 2016-2-16 16:46:03

dsweiliang 发表于 2016-2-16 10:31
为什么这么多人喜欢这个视频呢?

黑白手绘,音乐动感二次元,画面容易被移植到其他平台上
回复

使用道具 举报

Geemi  初级技匠

发表于 2016-2-17 11:06:38

还是黑白好看………………囧
回复

使用道具 举报

luna  初级技神

发表于 2016-2-17 14:05:27

Geemi 发表于 2016-2-17 11:06
还是黑白好看………………囧

不知道为什么,这位仁兄戳中了我的笑点~~
回复

使用道具 举报

mickey  NPC

发表于 2016-2-17 16:51:35

曾经用Arduino+SD卡模块+LCD12864+MP3模块尝试做过,动画显示没有成功。
回复

使用道具 举报

gaesar1  见习技师

发表于 2016-2-17 16:58:23

挺不错的
回复

使用道具 举报

virtualwiz  中级技匠

发表于 2016-2-17 17:48:10

大神~效果真不错啊:lol
没想到这么干可以有这么流畅的动画~12864是不是不能刷新这么快?
回复

使用道具 举报

吹口琴的钢铁侠  初级技匠
 楼主|

发表于 2016-2-17 19:55:49

mickey 发表于 2016-2-17 16:51
曾经用Arduino+SD卡模块+LCD12864+MP3模块尝试做过,动画显示没有成功。

Arduino 性能堪忧啊,硬伤没办法。。
回复

使用道具 举报

吹口琴的钢铁侠  初级技匠
 楼主|

发表于 2016-2-17 19:56:51

virtualwiz 发表于 2016-2-17 17:48
大神~效果真不错啊
没想到这么干可以有这么流畅的动画~12864是不是不能刷新这么快? ...

没试过,树莓派可能可以吧,主要还是看性能
回复

使用道具 举报

mickey  NPC

发表于 2016-3-2 17:16:04

吹口琴的钢铁侠 发表于 2016-2-17 19:55
Arduino 性能堪忧啊,硬伤没办法。。

曾有人用51单片机做成功过,所以Arduino是可以实现,速度足够了。
回复

使用道具 举报

iooops  中级技匠

发表于 2016-3-19 21:00:39

   也来影院占个座
回复

使用道具 举报

yoyojacky  初级技匠 来自手机

发表于 2016-3-24 02:51:15

决定一试
回复

使用道具 举报

arduino菜鸟  学徒

发表于 2016-8-2 21:14:00

我的播放有问题,播放的时候屏幕会不断地滚动,不知道为什么:'(
回复

使用道具 举报

yoyojacky  初级技匠 来自手机

发表于 2016-8-3 22:48:08

回复

使用道具 举报

吹口琴的钢铁侠  初级技匠
 楼主|

发表于 2016-8-24 11:09:35

arduino菜鸟 发表于 2016-8-2 21:14
我的播放有问题,播放的时候屏幕会不断地滚动,不知道为什么

具体是什么样子
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2022 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail