Статья Пишем конвертер видео и аудио файлов на Python: бесплатно и без рекламы.

Кирилл

Команда форума
Администратор
Ассоциация VN
Сообщения
14,296
Реакции
6,301
Привет!

Жена попросила сообразить для нее конвертер файлов - говорит что то, что пробовала скачать с сети либо тормозное, либо содержит кучу рекламы, либо платное.
Поверил на слово, да и стало интересно сделать свое.
Итак, пишем программу, которая конвертирует видео и аудио файлы в нужный формат.

Забегу вперед и сообщу, что все исходные файлы для тех, кому лень или не хочется читать в конце темы прикреплены.
Сначала хотел сделать на VB, но не стал в связи с тем, что не нравится потребность использовать системные API, которые без справочника не разобрать.
Поэтому Python, так как на нем можно писать не особо заглядывая в документацию.

Что еще. Не очень хотелось углубляться в недра кодеков и прочего - по этому решил, что сделаю просто обертку готовой консольной программы.
Как, впрочем, и делают многие другие разработчики. За основу взял ffmpeg.
Скачайте программу и поместите распакованный каталог из архива в корень диска С, если будете использовать мою программу как есть или в другое место - но потребуется в код дописать путь к ней.

Итак, сначала я подумал, что мне потребуется какой то визуальный интерфейс и кнопки управления, а так же информационное поле.

Вот как это выглядело в моей голове:

1586078650456.png


Теперь напишем основу программы - обозначим элементы управления, составим список функции.

Так как нужен интерфейс и выпендриваться с витиеватым дизайном задачи нет, то обойдемся стандартными библиотеками:
Tkinter - для отрисовки окна программы и ее содержимого
os - для управления файлами и их адресами.

Примерно так:

Python:
import tkinter as tk
from tkinter import filedialog
import tkinter.ttk as ttk
import os
root = tk.Tk()

path_output = ''

def f_inp():
    '''
        Диалоговое окно выбора исходных файлов
    '''
    pass


def f_out():
    '''
        Диалоговое окно выбора пути сохранения файлов
    '''
    pass

def run():
    '''
        Команда выполнить конвертацию
    '''
    pass


# Информационный Label
lb_info = tk.Label(text = 'Выберите один или несколько файлов: ')
lb_info.place(y = 10, x = 10)

# Кнопка выбора исходных файлов
bt_input = tk.Button(root, text = '   ...   ', command = f_inp)
bt_input.place(y = 10, x = 235)

# текстовое поле с информацией
txt = tk.Text(width = 70, state = 'disable')
txt.place(y = 80, x = 10)

# Информационный Label
lb_output = tk.Label(text = 'Выберите каталог для сохранения файлов:')
lb_output.place(y = 10, x = 300)

# Кнопка выбора каталог сохранения файлов
bt_output = tk.Button(root, text = '   ...   ', command = f_out)
bt_output.place(y = 10, x = 545)

# Информационный Label
lb_format_info = tk.Label(text = 'В какой формат конвертировать файл(ы)?')
lb_format_info.place(y = 40, x = 10)

# Combobox с вариантами выбора форматов файлов на выходе
list_format_file = ttk.Combobox(root,
                                values = [u'mp4', u'avi', u'mkv'],
                                height=3, state = 'readonly')
list_format_file.current(0)
list_format_file.place(y = 40, x = 250)

# Кнопка выполнить
bt_run = tk.Button(root, text = 'Выполнить', command = run, state = 'disable')
bt_run.place(y = 40, x = 510)

# Конфигурация окна программы
root.geometry('600x500')
root.title('Video Converter Free')
root.mainloop()
if __name__ == '__main__':
    pass

А дальше все просто - на этот "скелет" наращиваем "мясо" - то есть остаток кода.

Обратите внимание - Combobox с вариантами выбора формата на выходе файлов у меня не велик:
[u'mp4', u'avi', u'mkv']
Но программа легко "переваривает" и прочие форматы - если нужно добавить новый, то просто допишите их в эту строку в кавыках и через запятую.
А так же возможно работать и с аудиофайлами.

Функция f_inp должна записывать в текстовое поле перечень выбранных файлов, а так же задавать исходный каталог с файлами в качестве выходного на тот случай, если пользователь не решится выбрать куда их сохранить.
То есть по умолчанию сохраняем туда, откуда взяли.

Функция f_out имеет только одну цель - что бы пользователь, выбрав куда он хочет сохранить файлы на выходе был уверен, что так оно и будет)

Функция run отвечает за выполнение операции конвертации.

В переменную util_path мы сохраним путь до утилиты ffmpeg, которую вы уже ранее должны были скачать: 'C:/ffmpeg/bin/ffmpeg.exe'
Обратите внимание, что слэш обратный.

Далее мы циклом перебираем список выбранных файлов, который уже находится в текстовом поле.
При каждой итерации мы должны убедиться, что не пытаемся обработать пустую строку - именно для этого я сделал пустую строку в конце списка выбранных файлов.

Затем извлекаем выбранный каталог для сохранения файлов, имена самих файлов, выбранный формат сохранения и все это передаем в качестве аргумента при вызове утилиты ffmpeg.

То, что обработано - подкрашиваем желтым цветом и подчеркиваем.

Нужную информацию выводим в текстовое поле.
Все.

Python:
import tkinter as tk
from tkinter import filedialog
import tkinter.ttk as ttk
import os
root = tk.Tk()

path_output = ''
list_format = ['mp4', 'avi', 'mkv']

def f_inp():
    '''
        Диалоговое окно выбора исходных файлов
    '''
    global path_output
    fd = tk.filedialog.askopenfilenames(title = "Выберите медиафайл",
                                        multiple=True)
    if fd:
        txt.config(state = 'normal')
        txt.delete(1.0, 'end')
        for i in fd:
            txt.insert('end', i +'\n')
            if path_output == '':
                path_output = os.path.dirname(i)
        txt.insert('end', '\n' + 'Конец списка' + '\n')
        txt.config(state = 'disable')
        bt_run.config(state = 'normal')


def f_out():
    '''
        Диалоговое окно выбора пути сохранения файлов
    '''
    global path_output
    path_output = tk.filedialog.askdirectory(
                               title = 'Укажите каталог для сохранения файлов')
    txt.config(state = 'normal')
    txt.insert('end', '\n' + 'Сохранить в: ' +'\n' + path_output +'\n')
    txt.config(state = 'disable')

def run():
    '''
        Команда выполнить конвертацию
    '''
    util_path = 'C:/ffmpeg/bin/ffmpeg.exe'

    if os.path.isfile(util_path):
        for i in txt.get(1.0, 'end').split('\n'):
            if i:
                output_file = (path_output
                               + '/' + os.path.basename(i).rsplit('.', 1)[0]
                               + '.' + list_format_file.get())
                txt.config(state = 'normal')
                txt.tag_add(i, 1.0, 'end')
                txt.tag_config(i, background ='yellow', underline=1)

                try:
                    os.system(util_path + ' -i ' + i +' ' + output_file)
                except:
                    txt.insert('end', '\n' +
                               'Упс! Не удается конвертировать файл: ')
                    txt.insert('end', '\n' + i)
            else:
                break
        txt.insert('end', '\n' + 'Операция завершена')
        txt.config(state = 'disable')


    else:
        txt.config(state = 'normal')
        txt.insert('end', '\n' + 'Не нейден файл "C:\\ffmpeg\\bin\\ffmpeg.exe"')
        txt.insert('end', '\n' + 'Убедитесь, что он доступен.')
        txt.config(state = 'disable')

lb_info = tk.Label(text = 'Выберите один или несколько файлов: ')
lb_info.place(y = 10, x = 10)

bt_input = tk.Button(root, text = '   ...   ', command = f_inp)
bt_input.place(y = 10, x = 235)

txt = tk.Text(width = 70, state = 'disable')
txt.place(y = 80, x = 10)

lb_output = tk.Label(text = 'Выберите каталог для сохранения файлов:')
lb_output.place(y = 10, x = 300)

bt_output = tk.Button(root, text = '   ...   ', command = f_out)
bt_output.place(y = 10, x = 545)


lb_format_info = tk.Label(text = 'В какой формат конвертировать файл(ы)?')
lb_format_info.place(y = 40, x = 10)

list_format_file = ttk.Combobox(root,
                                values = [u'mp4', u'avi', u'mkv'],
                                height=3, state = 'readonly')
list_format_file.current(0)
list_format_file.place(y = 40, x = 250)

bt_run = tk.Button(root, text = 'Выполнить', command = run, state = 'disable')
bt_run.place(y = 40, x = 510)


root.geometry('600x500')
root.title('Video Converter Free')
root.mainloop()
if __name__ == '__main__':
    pass

Весь проект сохраняем с расширением .pyw - тогда при запуске скрипта не будет маячить консоль.

Либо же, если вы планируете использовать программу на компьютере, где нет интерпретатора Python - можете упаковать проект в exe файл.
Для этого можете воспользоваться вот этой программой:

Python exe packer - программа для сборки скриптов Python в exe файлы 1.1.0

Только имейте в виду, что для 32 и 64 разрядных систем надо паковать раздельно.

Исходный код в файле прикрепил, как и обещал.
 

Вложения

  • Конвертер видео.7z
    1.4 KB · Просмотры: 62
Последнее редактирование:

Кирилл

Команда форума
Администратор
Ассоциация VN
Сообщения
14,296
Реакции
6,301
Судя по всему - можно.

Но не всегда оправдано...привязка через изменение аргумента.
Это чисто праздное любопытство?
 

monowar

Активный пользователь
Сообщения
349
Реакции
595
@Кирилл, нет не праздное . Была потребность (да и сейчас ,но в меньшей степени) конвертировать из TS в мр4 . Через процессор время много уходило ,а видео карту не мог загрузить т.к. карта AMD , NVIDIA можно задействовать , а AMD не получалось. Поэтому и спросил
 

Кирилл

Команда форума
Администратор
Ассоциация VN
Сообщения
14,296
Реакции
6,301
Под AMD можно вот тут посмотреть, но тестировать не на чем.
Попробуйте в командной строке:

ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -i файл_исходный.mp4 -c:v libx264 -crf 20 файл_на_выходе.mp4

Если отработает нормально - помогу исправить код программы.
 

monowar

Активный пользователь
Сообщения
349
Реакции
595
Много чего просмотрел и мой вывод такой ,кто пишет ffmpeg у них видеокарты NVIDIA . Наткнулся на статью ,там писали ,чтобы ffmpeg подключала AMD карту нужно перекомпиллировать ffmpeg с amf , но это надо делать на Linux (ну нет у меня Linux ) и я ,навряд-ли ,это сделал бы.
Я пробовал так ffmpeg -y -hwaccel hevc_amf dxva2 -i "C:\Users\a\Videos\Madeon.avi" "C:\Users\a\Videos\Madeon.mp4" не поддерживает hevc_amf
Сейчас попробую твой вариант (я в блогах видел, правда перешёл по адресу только в Brave , а Firefox и Waterfox не захотели открывать сайт - не защищённое соединение (похоже надо about править) )

Попробовал с mp4 в avi Результат

Изменил (убрал -hwaccel vaapi ) ffmpeg -hwaccel_device /dev/dri/renderD128 -i "C:\Users\a\Videos\a90.mp4" -c:v libx264 -crf 20 "C:\Users\a\Videos\a90.avi" конвертация пошла ,но скорость маленькая
 
Последнее редактирование:

monowar

Активный пользователь
Сообщения
349
Реакции
595
Вообще-то скорость с подключением видюхи должна возрасти в 2-3 раза min, у меня s = 1.20
Сейчас посмотрю какая скорость через процессор без видюхи
Вот Результат
 
Последнее редактирование:
Сверху Снизу