2
0

res.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #!/usr/bin/env python2
  2. # -*- coding: UTF-8 -*-
  3. # File: res.py
  4. # Date: Sat Dec 20 16:26:51 2014 +0800
  5. # Author: Yuxin Wu <[email protected]>
  6. import glob
  7. import os
  8. import Image
  9. import cStringIO
  10. import base64
  11. import logging
  12. import eyed3
  13. logger = logging.getLogger(__name__)
  14. from lib.avatar import AvatarReader
  15. VOICE_DIRNAME = 'voice2'
  16. IMG_DIRNAME = 'image2'
  17. JPEG_QUALITY = 50
  18. class Resource(object):
  19. """ multimedia resources in chat"""
  20. def __init__(self, res_dir):
  21. assert os.path.isdir(res_dir), "No such directory: {}".format(res_dir)
  22. self.res_dir = res_dir
  23. self.img_dir = os.path.join(res_dir, IMG_DIRNAME)
  24. assert os.path.isdir(self.img_dir), \
  25. "No such directory: {}".format(self.img_dir)
  26. self.avt_reader = AvatarReader(self.res_dir)
  27. self.init()
  28. def init(self):
  29. """ load some index in memory"""
  30. self.speak_data = {}
  31. for root, subdirs, files in os.walk(
  32. os.path.join(self.res_dir, VOICE_DIRNAME)):
  33. if subdirs:
  34. continue
  35. for f in files:
  36. if not f.endswith('amr'):
  37. continue
  38. full_path = os.path.join(root, f)
  39. key = f[4:-4] # msg_xxxxx.amr
  40. assert len(key) == 26, \
  41. "Error interpreting the protocol, this is a bug!"
  42. self.speak_data[key] = full_path
  43. def get_voice_mp3(self, imgpath):
  44. """ return base64 string, and voice duration"""
  45. amr_fpath = self.speak_data[imgpath]
  46. assert amr_fpath.endswith('.amr')
  47. mp3_file = os.path.join('/tmp',
  48. os.path.basename(amr_fpath)[:-4] + '.mp3')
  49. # TODO is there a library to use?
  50. ret = os.system('sox {} {}'.format(amr_fpath, mp3_file))
  51. if ret != 0:
  52. logger.warn("Sox Failed!")
  53. return ""
  54. mp3_string = open(mp3_file, 'rb').read()
  55. duration = eyed3.load(mp3_file).info.time_secs
  56. os.unlink(mp3_file)
  57. return base64.b64encode(mp3_string), duration
  58. @staticmethod
  59. def get_file_b64(fname):
  60. data = open(fname, 'rb').read()
  61. return base64.b64encode(data)
  62. def get_avatar(self, username):
  63. """ return base64 string"""
  64. ret = self.avt_reader.get_avatar(username)
  65. if ret is None:
  66. return ""
  67. im = Image.fromarray(ret)
  68. buf = cStringIO.StringIO()
  69. im.save(buf, 'JPEG', quality=JPEG_QUALITY)
  70. jpeg_str = buf.getvalue()
  71. return base64.b64encode(jpeg_str)
  72. def get_img_file(self, fnames):
  73. """ fnames: a list of filename to search for
  74. return (filename, filename) of (big, small) image.
  75. could be empty string.
  76. """
  77. cands = []
  78. for fname in fnames:
  79. dir1, dir2 = fname[:2], fname[2:4]
  80. dirname = os.path.join(self.img_dir, dir1, dir2)
  81. if not os.path.isdir(dirname):
  82. logger.warn("Directory not found: {}".format(dirname))
  83. continue
  84. for f in os.listdir(dirname):
  85. if fname in f:
  86. full_name = os.path.join(dirname, f)
  87. size = os.path.getsize(full_name)
  88. if size > 0:
  89. cands.append((full_name, size))
  90. if not cands:
  91. return ("", "")
  92. cands = sorted(cands, key=lambda x: x[1])
  93. def name_is_thumbnail(name):
  94. return os.path.basename(name).startswith('th_') \
  95. and not name.endswith('hd')
  96. if len(cands) == 1:
  97. name = cands[0][0]
  98. if name_is_thumbnail(name):
  99. # thumbnail
  100. return ("", name)
  101. else:
  102. logger.warn("Found big image but not thumbnail: {}".format(fname))
  103. return (name, "")
  104. big = cands[-1]
  105. ths = filter(name_is_thumbnail, [k[0] for k in cands])
  106. if not ths:
  107. return (big[0], "")
  108. return (big[0], ths[0])
  109. def get_img(self, fnames):
  110. """ return two base64 jpg string"""
  111. big_file, small_file = self.get_img_file(fnames)
  112. def get_jpg_b64(img_file):
  113. if not img_file:
  114. return None
  115. if not img_file.endswith('jpg'):
  116. # possibly not jpg
  117. im = Image.open(open(img_file, 'rb'))
  118. buf = cStringIO.StringIO()
  119. im.save(buf, 'JPEG', quality=JPEG_QUALITY)
  120. return base64.b64encode(buf.getvalue())
  121. return Resource.get_file_b64(img_file)
  122. big_file = get_jpg_b64(big_file)
  123. small_file = get_jpg_b64(small_file)
  124. if big_file and not small_file:
  125. # TODO resize big to a thumbnail
  126. pass
  127. return (big_file, small_file)