Я использую ffmpeg
в Python3 для запуска команды :
process = subprocess.Popen(
command,
stdout=open(os.devnull, 'wb'),
stdin=subprocess.PIPE,
stderr=subprocess.PIPE)
# Write data to STDIN.
try:
process.stdin.write(data.astype('<f4').tostring())
except IOError:
raise IOError(f'FFMPEG error: {process.stderr.read()}')
# Clean process.
process.stdin.close()
if process.stderr is not None:
process.stderr.close()
process.wait()
, где data
представляет волновой файл, следовательно, он добавляется к stdin
. Этот код имеет утечку памяти. Память не освобождается, фактически, если мы выполняем трассировку памяти:
is_tracing = tracemalloc.is_tracing()
if not is_tracing:
nframe = 6
tracemalloc.start(nframe)
current_mem, peak_mem = tracemalloc.get_traced_memory()
overhead = tracemalloc.get_tracemalloc_memory()
summary = "traced memory: %d KiB peak: %d KiB overhead: %d KiB" % (
int(current_mem // 1024), int(peak_mem // 1024), int(overhead // 1024)
)
print( "before save", summary )
process = subprocess.Popen(
command,
stdout=open(os.devnull, 'wb'),
stdin=subprocess.PIPE,
stderr=subprocess.PIPE)
try:
process.stdin.write(data.astype('<f4').tostring())
except IOError:
raise IOError(f'FFMPEG error: {process.stderr.read()}')
process.stdin.close()
if process.stderr is not None:
process.stderr.close()
process.wait()
current_mem, peak_mem = tracemalloc.get_traced_memory()
overhead = tracemalloc.get_tracemalloc_memory()
summary = "traced memory: %d KiB peak: %d KiB overhead: %d KiB" % (
int(current_mem // 1024), int(peak_mem // 1024), int(overhead // 1024)
)
print( "after save", summary )
и выполняем ее больше раз, это даст
after save traced memory: 18 KiB peak: 1419 KiB overhead: 10 KiB
before save traced memory: 27459 KiB peak: 28152 KiB overhead: 28293 KiB
after save traced memory: 27384 KiB peak: 28872 KiB overhead: 28267 KiB
before save traced memory: 52707 KiB peak: 53400 KiB overhead: 53132 KiB
after save traced memory: 52653 KiB peak: 54120 KiB overhead: 53109 KiB
В частности, выполненный ffmpeg command
был
command = (
self._get_command_builder()
.flag('-y')
.opt('-loglevel', 'error')
.opt('-f', 'f32le')
.opt('-ar', sample_rate)
.opt('-ac', data.shape[1])
.opt('-i', '-')
.flag('-vn')
.opt('-acodec', codec)
.opt('-ar', sample_rate)
.opt('-strict', '-2')
.opt('-ab', bitrate)
.flag(path)
.command())
Какая переменная утечка памяти? Я пытался очистить data
и грипп sh стандартный ввод без какого-либо успеха. Я также пытался запустить в threading.Thread
как:
class MyClass(threading.Thread):
def __init__(self, *args):
self.stdout = None
self.stderr = None
self.args = args
threading.Thread.__init__(self)
def run(self):
command = self.args[ 0 ]
data = self.args[ 1 ]
process = subprocess.Popen(
command,
stdout=open(os.devnull, 'wb'),
stdin=subprocess.PIPE,
stderr=subprocess.PIPE)
try:
process.stdin.write(data.astype('<f4').tostring())
except IOError:
raise IOError(f'FFMPEG error: {process.stderr.read()}')
self.stdout, self.stderr = process.communicate()
, а затем
myclass = MyClass(command, data)
myclass.start()
myclass.join()