После недолгих поисков готового пакета на Golang по редактированию видео — я понял, что ничего более-менее дельного в открытом доступе нет. Для одного моего проекта я использовал Python библиотеку moviepy которая хоть и медленная, но выполняла все нужные мне задачи. Мне часто нужно обрезать видео, склеить видео фрагменты и другие рутинные задачи для которых лень открыть Premiere Pro.
Я решил создать свой собственный пакет для решения простых задач по видео редактированию. Название у него MovieGo (есть проект MoviePy от которого я и вдохновился).
Рекомендуем вам супер TELEGRAM канал по Golang где собраны все материалы для качественного изучения языка. Удивите всех своими знаниями на собеседовании! 😎
Мы публикуем в паблике ВК и Telegram качественные обучающие материалы для быстрого изучения Go. Подпишитесь на нас в ВК и в Telegram. Поддержите сообщество Go программистов.
Поддержи проект на Github
Если тебе интересны такие проекты и ты хочешь увидеть их развитие, то не забудь поставить звездочку этому проекту на Github Ссылка на пакет: https://github.com/mowshon/moviego
|
В основном «под капотом» у данного пакета лежит библиотека FFMPEG. Все манипуляции над видео выполняются через вызов нужных команд в консоль. Ниже будут предоставлены несколько примеров того, что можно сделать на текущий момент с этим пакетом.
Установка
1 |
go get github.com/mowshon/moviego@v1.0.0 |
Изменить размер видео в Golang
Структура Video
от пакета MovieGo
предоставляет три метода для изменения размера видео.
ResizeByWidth( новая ширина )
— данный метод меняет ширину видео и автоматически, сохраняя пропорции, меняет и высоту видео;ResizeByHeight( новая высота )
— метод меняет высоту видео и обновляет ширину сохраняя пропорции;Resize( новая ширина, новая высота )
— метод меняет ширину и высоту видео.
Пример кода на Golang как менять ширину и высоту видео:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package main import ( "github.com/mowshon/moviego" ) func main() { first, _ := moviego.Load("forest.mp4") first.ResizeByWidth(500).Output("resized-by-width.mp4").Run() first.ResizeByWidth(150).Output("resized-by-height.mp4").Run() first.Resize(1000, 500).Output("resized.mp4").Run() } |
Если выполнить данные манипуляции в FFMPEG, то команды выглядели бы следующим образом:
1 2 3 |
ffmpeg -i forest.mp4 -vf scale=500:210 resized-by-width.mp4 -y ffmpeg -i forest.mp4 -vf scale=150:62 resized-by-height.mp4 -y ffmpeg -i forest.mp4 -vf scale=1000:500 resized.mp4 -y |
Обрезать видео на фрагменты в Golang
Самая частая задача которая встречается, это обрезка основного видео на части. Для этого мы будем использовать метод SubClip(начало, конец)
чтобы обрезать кусочки видео из нашего основного видео.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package main import ( "github.com/mowshon/moviego" "log" ) func main() { first, _ := moviego.Load("forest.mp4") // Обрезка видео начиная с 3 секунды до 5 секунды. err := first.SubClip(3, 5).Output("final.mp4").Run() if err != nil { log.Fatal(err) } } |
Эквивалент данного действия в FFMPEG:
1 |
ffmpeg -i forest.mp4 -ss 3.000000 -to 5.000000 -vf scale=1280:536 final.mp4 -y |
Объединение нескольких видео в одно в Golang
Конкатенация нескольких видео в одно, так же является частой задачей при редактировании видео. Для этой задачи у нас есть функция Concat
которая возвращает структуру Video
и ошибку (если такая возникла) и уже к ней применяем метод .Out("название-файла.mp4").Run()
для рендеринга финального видео.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package main import ( "github.com/mowshon/moviego" "log" ) func main() { first, _ := moviego.Load("forest.mp4") second, _ := moviego.Load("sky.mp4") // Объединение нескольких видео в одно. finalVideo, err := moviego.Concat([]moviego.Video{ first, // Первое видео без эффектов. second, // Второе видео тоже без эффектов. first.SubClip(1, 3), // Из первого видео обрезаем 2 секунды. second.SubClip(5.3, 10.5), // Из второго видео обрезаем 5 секунд. first.FadeIn(0, 5).FadeOut(5), // Для оригинального первого видео добавляем несколько эффектов. }) if err != nil { log.Fatal(err) } renderErr := finalVideo.Output("final.mp4").Run() if err != nil { log.Fatal(renderErr) } } |
Функция Concat
принимает слайс типа []moviego.Video
в котором добавляем нужные нам фрагменты видео. Можно применяет различные доступные эффекты к видео из слайса. Функция будет рендерить их по очереди потом объединит их в одно видео.
Добавление переходов Fade-in, Fade-out для видео
Здесь представлены 4 метода работы с эффектом Fade (In, Out). Два метода для видео и два метода для аудио-дорожки из видео.
.FadeIn( начало, продолжительность )
— добавляет эффект Fade-In (переход от полностью черного экрана к нормальному видео);.FadeOut( длительность до конца видео )
— метод добавляет эффект Fade-Out, от нормальной картинки постепенно затухает в полностью черный экран. В зависимости от указанной «длительности» затухания, данный эффект добавится в конце видео, его начало будет в отметке= (videoDuration - fadeOutDuration)
;.AudioFadeIn( начало, длительность )
— как и в случае с методом FadeIn для видео, данный метод полностью убавит звук в начале видео и постепенно вернет звук в норму в зависимости от указанной «длительности» эффекта;.AudioFadeOut( длительность )
— данный метод добавит эффект «затухания» аудио-дорожки в конце видео.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package main import ( "github.com/mowshon/moviego" ) func main() { first, _ := moviego.Load("forest.mp4") // Добавляем оба эффекта Fade-in и Fade-out. first.FadeIn(0, 3).FadeOut(5).Output("fade-in-with-fade-out.mp4").Run() // Обрезаем видео и добавляем эффект Fade-in. first.SubClip(5.20, 10).FadeIn(0, 3).Output("cut-fade-in.mp4").Run() // Полностью убираем звук до 0.5 секунды видео // и постепенно возвращаем его к секунде 4. first.AudioFadeIn(0.5, 4).Output("audio-fade-in.mp4").Run() // Угасание видео и аудио в самом конце за последние 5 секунд видео. first.FadeOut(5).AudioFadeOut(5).Output("fade-out.mp4").Run() } |
Как вы уже заметили, благодаря этому пакету можно комбинировать несколько методов в цепи вызовов друг за другом при этом не меняя состояние структуры полученную от первого вызова видео файла.
Создание скриншота из видео в Golang
Тут все весьма просто. Берем метод Screenshot
и указываем ему нужную нам секунду из видео и делаем скриншот.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package main import ( "github.com/mowshon/moviego" ) func main() { first, _ := moviego.Load("forest.mp4") // Создаем обычный скриншот. first.Screenshot(2, "simple-screen.png") // Применяем эффект FadeIn и FadeOut и скриншотим момент применения фильтра. first.FadeIn(0, 6).FadeOut(5).Screenshot(2, "screen.png") } |
Одна из «фишек» этого метода и пакета в целом, это возможность получить скриншот после всей цепи примененных изменений к основному видео. Если вы применили эффект FadeIn с длительностью в 6 секунд и попробуйте сделать скриншот во 2 секунде видео, то получите вот такой результат:
simple-screen.png (Без изменений) | screen.png (FadeIn) |
Итоги
Данный пакет еще находится в стадии развития, я постараюсь улучшить функционал по мере появления новых задач и свободного времени. Код далёк от идеала и если у вас есть желание, то можете загрузить Pull-Request с предложениями по улучшению кода. Надеюсь данный пакет будет вам полезен!
Если будут вопросы, то жду вас в разделе: Issues от Github
Администрирую данный сайт с целью распространения как можно большего объема обучающего материала для языка программирования Go. В IT с 2008 года, с тех пор изучаю и применяю интересующие меня технологии. Проявляю огромный интерес к машинному обучению и анализу данных.
E-mail: vasile.buldumac@ati.utm.md
Образование
Технический Университет Молдовы (utm.md), Факультет Вычислительной Техники, Информатики и Микроэлектроники
- 2014 — 2018 Universitatea Tehnică a Moldovei, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Universitatea Tehnică a Moldovei, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»