Перекодирование m4a в flac, с помощью скрипта на python 3
Простая задача по перекодированию музыки из m4a в flac или mp3 встретилась с особенностями оболочки bash в ubuntu.
Для примера, название “-01 Test Of music.m4a”, не будет обработано т.к. впереди идет знак минус “-”, который не обрабатывается правильно без экранирования в bash скрипте. В самом названии так же могут встретиться управляющие конструкции. Задача вполне решаема, но гораздо удобнее использовать скрипт на python.
Особенности:
Для перекодирования используется утилита ffmpeg, и ее вызов через subprocess
Пример того как на BASH выглядит установка и перекодирование единичного файла с пробелами в названии.
sudo apt-get install ffmpeg
ffmpeg -i "01 Test Of music.m4a" -f flac "01 Test Of music.ffmpeg.flac"
Скрипт полностью рабочий, выполняет полностью задачу, но далек от идеала. Примечания смотрите в коде и ниже в пояснениях.
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import os
import subprocess
class cd:
"""Context manager for changing the current working directory"""
def __init__(self, newPath):
self.newPath = os.path.expanduser(newPath)
def __enter__(self):
self.savedPath = os.getcwd()
os.chdir(self.newPath)
def __exit__(self, etype, value, traceback):
os.chdir(self.savedPath)
# !!!! обратить внимание на путь, прописан жестко для пользователя user в ubuntu
for root, dirs, files in os.walk("/home/user/Музыка/"):
for file in files:
if file.endswith(".m4a"):
print("Путь к файлу " + os.path.join(root, file))
# command = "/usr/bin/ffmpeg -i '" + file + "' -f flac '" + file + ".flac'"
command = ['ffmpeg']
command.append('-i')
command.append(file)
command.append('-f')
command.append('flac')
command.append(file + '.flac')
with cd(root):
print (command)
subprocess.call(command)
print("======================================================================")
Пояснения:
- Менеджер контекста cd для subprocess можно было заменить на параметр cwd при вызове функции, но при разработке были ошибки, поэтому был использован работающий код из другого проекта. os.chdir(root) - сменит директорию для родительского проекта, для дочернего subprocess работать не будет.
- subrocess работает в режиме псевдо эмуляции терминала, где все изначально экранировано, поэтому дополнительно делать ничего не нужно, но если очень нужно, то можно использовать аргумент функции shell=True. Получаем полностью все возможности и недостатки
- os.walk("/home/user/Музыка/") - прописан жестко, т.к. не требовалась универсальность, нужен был только быстрый результат. Заменить на своё
- ffmpeg универсальный конвертер, если нужен другой формат, достаточно заменить -f flac на -f mp3. Входной файл не имеет большой роли, если его можно перекодировать через ffmpeg, ограничения заданы при поиске в скрипте file.endswith(".m4a")
- subprocess принимает на вход список, в простом варианте для строке bash достаточно было бы применить split по пробелу, но проблема в том, что наш файл может содержать пробел, поэтому быстрее составить список вручную через command.append().
- Название файла (file + ‘.flac’) сделано по нескольким причинам, основная - удобство проверки, все ли прошло успешно, т.к. оригинал не удаляется скриптом. В последующем с помощью find удаляются оригиналы m4a, которые больше не нужны
Если файл flac уже есть в директории, рядом с файлом m4a, то ffmpeg спрашивает что делать дальше, необходимо произвести выбор, иначе скрипт дальше работать не будет
Кроме ffmpeg, так же есть хорошая утилита avconv, форк-клон ffmpeg, но в данном случае она будет использовать теже способы, что и ffmpeg для перекодирования, поэтому использую оригинал
# пример установки и конвертирования через avconv
sudo aptitude install libav-tools
avconv -i "-01 Test Of music.m4a" -f flac "-01 Test Of music.avconv.flac"