Bladeren bron

speed up voice rendering

ppwwyyxx 11 jaren geleden
bovenliggende
commit
c2c9de8fcb
2 gewijzigde bestanden met toevoegingen van 36 en 20 verwijderingen
  1. 4 1
      lib/render.py
  2. 32 19
      lib/res.py

+ 4 - 1
lib/render.py

@@ -1,7 +1,7 @@
 #!/usr/bin/env python2
 # -*- coding: UTF-8 -*-
 # File: render.py
-# Date: Thu Jan 08 00:22:33 2015 +0800
+# Date: Thu Jan 08 00:53:11 2015 +0800
 # Author: Yuxin Wu <[email protected]>
 
 import os
@@ -192,6 +192,9 @@ class HTMLRender(object):
             talkers = set([talker_id])
         self.prepare_avatar_css(talkers)
 
+        voice_paths = [msg.imgPath for msg in msgs if msg.type == TYPE_SPEAK]
+        self.res.cache_voice_mp3(voice_paths)
+
         logger.info(u"Rendering {} messages of {}({})".format(
             len(msgs), self.parser.contacts[talker_id], talker_id))
 

+ 32 - 19
lib/res.py

@@ -1,7 +1,7 @@
 #!/usr/bin/env python2
 # -*- coding: UTF-8 -*-
 # File: res.py
-# Date: Thu Jan 08 00:08:43 2015 +0800
+# Date: Thu Jan 08 00:52:13 2015 +0800
 # Author: Yuxin Wu <[email protected]>
 
 import glob
@@ -13,6 +13,7 @@ import cStringIO
 import base64
 import logging
 import imghdr
+from multiprocessing import Pool
 logger = logging.getLogger(__name__)
 
 import pysox
@@ -27,6 +28,24 @@ IMG_DIRNAME = 'image2'
 EMOJI_DIRNAME = 'emoji'
 JPEG_QUALITY = 50
 
+def do_get_voice_mp3(amr_fpath):
+    """ return base64 string, and voice duration"""
+    assert amr_fpath.endswith('.amr')
+    mp3_file = os.path.join('/tmp',
+                            os.path.basename(amr_fpath)[:-4] + '.mp3')
+
+    infile = pysox.CSoxStream(amr_fpath)
+    outfile = pysox.CSoxStream(mp3_file, 'w', infile.get_signal())
+    chain = pysox.CEffectsChain(infile, outfile)
+    chain.flow_effects()
+    outfile.close()
+
+    signal = infile.get_signal().get_signalinfo()
+    duration = signal['length'] * 1.0 / signal['rate']
+    mp3_string = Resource.get_file_b64(mp3_file)
+    os.unlink(mp3_file)
+    return mp3_string, duration
+
 class Resource(object):
     """ multimedia resources in chat"""
     def __init__(self, res_dir):
@@ -53,25 +72,19 @@ class Resource(object):
                     "Error interpreting the protocol, this is potentially a bug!"
                 self.speak_data[key] = full_path
 
-    #@timing(total=True)
+    @timing(total=True)
     def get_voice_mp3(self, imgpath):
-        """ return base64 string, and voice duration"""
-        amr_fpath = self.speak_data[imgpath]
-        assert amr_fpath.endswith('.amr')
-        mp3_file = os.path.join('/tmp',
-                                os.path.basename(amr_fpath)[:-4] + '.mp3')
-
-        infile = pysox.CSoxStream(amr_fpath)
-        outfile = pysox.CSoxStream(mp3_file, 'w', infile.get_signal())
-        chain = pysox.CEffectsChain(infile, outfile)
-        chain.flow_effects()
-        outfile.close()
-
-        signal = infile.get_signal().get_signalinfo()
-        duration = signal['length'] * 1.0 / signal['rate']
-        mp3_string = Resource.get_file_b64(mp3_file)
-        os.unlink(mp3_file)
-        return mp3_string, duration
+        idx = self.voice_cache_idx.get(imgpath)
+        if not idx:
+            return do_get_voice_mp3(self.speak_data[imgpath])
+        return self.voice_cache[idx].get()
+
+    def cache_voice_mp3(self, voice_paths):
+        """ for speed """
+        self.voice_cache_idx = {k: idx for idx, k in enumerate(voice_paths)}
+        pool = Pool(3)
+        self.voice_cache = [pool.apply_async(do_get_voice_mp3,
+                                             (self.speak_data[k],)) for k in voice_paths]
 
     @staticmethod
     def get_file_b64(fname):