1 | # -*- coding: utf-8 -*- |
---|
2 | __author__ = 'sanmai' |
---|
3 | |
---|
4 | import subprocess |
---|
5 | import os |
---|
6 | import tempfile |
---|
7 | import pprint |
---|
8 | |
---|
9 | import logging |
---|
10 | |
---|
11 | logger = logging.getLogger('waitress') |
---|
12 | |
---|
13 | |
---|
14 | def get_full_ffmpeg_command(ffmpeg_command, input_mime_type, output_mime_type, output_media_file_path): |
---|
15 | full_ffmpeg_command = None |
---|
16 | |
---|
17 | if input_mime_type == "audio/x-wav" and output_mime_type == "audio/mp4": |
---|
18 | full_ffmpeg_command = [ffmpeg_command, |
---|
19 | "-i", "pipe:0", |
---|
20 | "-c:a", "libfdk_aac", |
---|
21 | "-b:a", "128k", |
---|
22 | "-nostdin", "-y", |
---|
23 | output_media_file_path] |
---|
24 | |
---|
25 | if full_ffmpeg_command is not None: |
---|
26 | logger.debug("full ffmpeg command: " + |
---|
27 | " ".join(full_ffmpeg_command)) |
---|
28 | |
---|
29 | return full_ffmpeg_command |
---|
30 | else: |
---|
31 | raise NotImplementedError() |
---|
32 | |
---|
33 | |
---|
34 | def convert(input_media_data, |
---|
35 | input_mime_type, |
---|
36 | output_mime_type, |
---|
37 | temp_directory_path, |
---|
38 | ffmpeg_command): |
---|
39 | try: |
---|
40 | output_media_file_fd, output_media_file_path = tempfile.mkstemp(dir=temp_directory_path, |
---|
41 | suffix=".m4a") |
---|
42 | os.close(output_media_file_fd) |
---|
43 | |
---|
44 | full_ffmpeg_command = get_full_ffmpeg_command(ffmpeg_command, |
---|
45 | input_mime_type, |
---|
46 | output_mime_type, |
---|
47 | output_media_file_path) |
---|
48 | |
---|
49 | with subprocess.Popen(full_ffmpeg_command, |
---|
50 | stdin=subprocess.PIPE, |
---|
51 | shell=False, |
---|
52 | universal_newlines=False) as process_obj: |
---|
53 | try: |
---|
54 | process_obj.stdin.write(input_media_data) |
---|
55 | process_obj.stdin.flush() |
---|
56 | process_obj.stdin.close() |
---|
57 | |
---|
58 | #stdout_data, stderr_data = process.communicate(input_media_data) |
---|
59 | |
---|
60 | except subprocess.TimeoutExpired as e: |
---|
61 | process_obj.kill() |
---|
62 | logger.error("ffmpeg process timed out: " |
---|
63 | + pprint.pprint(e)) |
---|
64 | raise |
---|
65 | else: |
---|
66 | try: |
---|
67 | with open(output_media_file_path, |
---|
68 | 'rb') as output_media_file: |
---|
69 | output_media_file_data = output_media_file.read() |
---|
70 | |
---|
71 | try: |
---|
72 | os.remove(output_media_file_path) |
---|
73 | except OSError as e: |
---|
74 | logger.error("Output media file at '{0}' could not be deleted after ffmpeg process.".format( |
---|
75 | output_media_file_path) + pprint.pprint(e)) |
---|
76 | raise |
---|
77 | else: |
---|
78 | return output_media_file_data |
---|
79 | except OSError as e: |
---|
80 | logger.error("Output media file at '{0}' could not be read after ffmpeg process.".format( |
---|
81 | output_media_file_path) + pprint.pprint(e)) |
---|
82 | raise |
---|
83 | except Exception as e: |
---|
84 | logger.error("Output media file at could not be created before " |
---|
85 | "ffmpeg process." + pprint.pprint(e)) |
---|
86 | raise |
---|
87 | |
---|
88 | |
---|
89 | class Converter(object): |
---|
90 | def __init__(self, |
---|
91 | caching, |
---|
92 | ffmpeg_command): |
---|
93 | |
---|
94 | self.caching = caching |
---|
95 | self.temp_directory_path = tempfile.mkdtemp(suffix='', |
---|
96 | prefix='media_conv__cache__') |
---|
97 | self.ffmpeg_command = ffmpeg_command |
---|
98 | |
---|
99 | if self.caching: |
---|
100 | import media_conv.cache |
---|
101 | |
---|
102 | def convert_media_file(self, |
---|
103 | input_media_data, |
---|
104 | input_mime_type, |
---|
105 | output_mime_type): |
---|
106 | if self.caching: |
---|
107 | logger.debug("Caching is enabled.") |
---|
108 | raise NotImplementedError |
---|
109 | else: |
---|
110 | output_media_data = convert(input_media_data=input_media_data, |
---|
111 | input_mime_type=input_mime_type, |
---|
112 | output_mime_type=output_mime_type, |
---|
113 | temp_directory_path=self.temp_directory_path, |
---|
114 | ffmpeg_command=self.ffmpeg_command) |
---|
115 | |
---|
116 | return output_media_data |
---|