Python

【音も消えません!】Pythonを使って動画速度を遅くする方法

【音も消えません!】Pythonを使って動画速度を遅くする方法
スポンサーリンク

こんにちは、さすを(@sasuwo0409)です。

いきなりですが、

OpenCVを使って、動画の速度を遅くしたはいいものの、音が消えた、、、

アプリを使って動画の速度を遅くするのはめんどくさい!

と思ってはいませんか?

今回の記事は、そのような悩みを解決するPythonを使って音を残しながら動画の速度を遅くする方法を紹介していきます。

それでは本文をどうぞ。

困っている女性
困っている女性

ダンスを覚えるために動画の速度を遅くしたいんだけど、いちいちアプリをつかうのめんどうなんだよなあ。

何かいい方法はないかしら。。。

さすを
さすを

これらの悩みを解決します!

この記事を読むとわかること:

Pythonを使って音を残したまま動画速度を遅くする方法

筆者の情報:

  • 現役システムエンジニア 兼 副業ブロガー
  • 過去に6,000万のPython案件を受注
  • 最近ハマっているドラマは「ドラゴン桜2」と「イチケイノカラス」

注意:

  • Windowsをもとに説明しています。Macの方は、多少操作感が違うと思いますが、ご承知ください。
  • 万が一失敗しても大丈夫なように、オリジナルのファイルは別に保存しておくことをおすすめします。

さすを
さすを

Pythonのインストールが終わっていない方は、まずは以下のサイトからインストールをおこなってください!

Pythonのインストール:

Windowsの方:
>>【Windows版】Pythonのインストール方法【画像を使ってわかりやすく解説】

Macの方:
>>MacにPythonをインストールする3つの方法!それぞれの利点と手順を紹介

さすを
さすを

「動画が遅くなれば音が消えても大丈夫」という方は以下の記事をご覧ください!

>>【コピペOK】PythonでOpenCVを使って動画の速度を変更する方法【編集の手間から卒業しよう】

スクリプトが少なく、処理時間も短いので手軽に作成することができます。


※0円のサンプルテキストという近道

独学よりプログラミングスクールの方が効果は出やすいですが、値段が高く、なかなか手を出しづらいですよね。techgymでは無料のサンプルテキストと解説動画をもらえるので、これを使ってお得にPythonの基礎を学ぶのもオススメです。

スポンサーリンク

1.Pythonを使って動画速度を遅くする方法

1.Pythonを使って動画速度を遅くする方法

1-1.【準備】必要なライブラリのインストール

Pythonを使って動画速度を遅くするには、いくつかのライブラリをインストールする必要があります。

必要なライブラリは以下の4つです。

  • numpy
  • soundfile
  • opencv
  • ffmpeg

各ライブラリのインストール方法はターミナルを開いて以下のコマンドを入力すればOKです。

さすを
さすを

検索欄に「ターミナル」と入力し、選択すると、ターミナルが出てきます!


numpy:

pip install numpy

soundfile:

pip install PySoundFile

opencv:

pip install opencv-python

ffmpegはファイルのダウンロードが必要です。こちらの記事がわかりやすかったです。

ffmpeg:

Windowsの方:
>>【簡単】FFMPEGをWindowsパソコンにインストールしよう

Macの方:
>>[Homebrew]MacにFFmpegをインストールする方法

ライブラリを削除する可能性があったり、特定のフォルダにライブラリをインストールしたい場合は、以下のような手順で解決できます。

  1. 特定のフォルダに移動する
  2. オプションをつける



例:デスクトップにライブラリをインストールする

1.ターミナルを開き、デスクトップに移動

cd desktop

2.オプションをつけながらライブラリをインストール

pip install numpy -t .

そのほかに、よく使うPythonライブラリは以下の記事で解説したので、参考にしていただけたらと思います。

>>【これだけ知っておけばOKです】 現役エンジニアもよく使う便利なPythonライブラリ22選

どのライブラリも便利でよく使うものばかりなので、今のうちにインストールをして、いつでも使える状態にしておくことをおすすめします。

1-2.動画速度を遅くするPythonスクリプト

今回のフォルダ構成、ファイルは以下の通りです。

フォルダのパスC:\Users\Sasuwo\Desktop\dance_example\input
ファイル名IMG_0001.MOV
IMG_0002.MOV
編集する動画のフォルダ構成(1)
編集する動画のフォルダ画面(1)
編集する動画のフォルダ画面(1)
フォルダのパスC:\Users\Sasuwo\Desktop\dance_example\output
ファイル名(空)
編集する動画のフォルダ構成(2)


編集する動画のフォルダ画面(2)
編集する動画のフォルダ画面(2)
フォルダのパスC:\Users\Saswo\Desktop\Python\slow_down_the_video
フォルダ名pycache
_soundfile_data
bin
cffi
cffi-1.14.5.dist-info
cv2
ffmpeg
ffmpeg_python-0.2.0.dist-info
numpy
numpy-1.20.3.dist-info
opencv_python-4.5.2.52.dist-info
pycparser
pycparser-2.20.dist-info
PySoundFile-0.9.0.post1.dist-info
ファイル名_cffi_backend.cp39-win_amd64.pyd
change_speed_and_music.py
soundfile.py
スクリプトのフォルダ構成(3)
編集する動画のフォルダ画面(3)
編集する動画のフォルダ画面(3)

C:\Users\Saswo\Desktop\Python\slow_down_the_videoのフォルダ構成は、後述する「change_video_and_music_speed.py」以外は、ライブラリをインストールすると自動的に入ります。

さすを
さすを

フォルダ名は、フォルダを開いてフォルダ名が書かれているボックスをクリックすればでてくるので、コピー&ペーストで使っていきましょう!

フォルダ名の探し方
フォルダ名の探し方

そして、動画の速度を変更を行うPythonのスクリプトはこちらです。

change_video_and_music_speed.py:

#必要なライブラリのインポート
import ffmpeg
import numpy as np
import soundfile as sf
import cv2
import os
import pathlib
import shutil
import time

print("処理を開始します。")

#処理時間の計測
start = time.time()

#読み込む動画のフォルダのパスを指定
input_dir = 'C:\\Users\\Yumiko\\Desktop\\dance_example\\input'

#編集が完了した動画を保存するフォルダのパスを指定
output_dir = 'C:\\Users\\Yumiko\\Desktop\\dance_example\\output'

#ビデオ速度を変更する関数
def video_speed_change(path_in, path_out, scale_factor, color_flag):

    # 動画読み込みの設定
    movie = cv2.VideoCapture(path_in)

    # 動画ファイル保存用の設定
    # 元動画のFPSを取得
    fps = int(movie.get(cv2.CAP_PROP_FPS))

    # 動画保存時のFPSはスケールファクターをかける
    fps_new = int(fps * scale_factor)

    # 動画の横幅を取得
    width = int(movie.get(cv2.CAP_PROP_FRAME_WIDTH))

    # 動画の縦幅を取得
    height = int(movie.get(cv2.CAP_PROP_FRAME_HEIGHT))

    # 動画保存時のfourcc設定(mp4用)
    fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')

    # 動画の仕様(ファイル名、fourcc, FPS, サイズ)
    video = cv2.VideoWriter(path_out, fourcc, fps_new, (width, height), color_flag)  

    # ファイルからフレームを1枚ずつ取得して動画処理後に保存する
    while True:
        # フレームを取得
        ret, frame = movie.read()        

        # 動画を保存する
        video.write(frame)

        # フレームが取得できない場合はループを抜ける
        if not ret:
            break

    # 撮影用オブジェクトとウィンドウを解放する
    movie.release()
    return

try:
    #ファイル一覧取得
    files = os.listdir(input_dir)
    print(files)

    for change_speed in files:
        #ファイルをコピー
        shutil.copy(input_dir + '\\' + change_speed,output_dir + '\\' + change_speed)
        path_in = input_dir + "\\" + change_speed

        # 保存する動画のパス
        path_out = input_dir + "\\" + change_speed + "_slow.mp4"

        # FPSにかけるスケールファクター
        scale_factor = 0.6
        
        # カラー動画はTrue, グレースケール動画はFalse
        color_flag = True               

        # 動画の再生速度を変更する関数を実行
        video_speed_change(path_in, path_out, scale_factor, color_flag)
    
        #音の抽出
        stream = ffmpeg.input(input_dir + '\\' + change_speed)

        stream = ffmpeg.output(stream, input_dir + '\\' + change_speed + '.wav')

        ffmpeg.run(stream)

        #読み込むオーディオファイルを設定
        filename = input_dir + '\\' + change_speed + '.wav'

        #何倍で再生するか指定(0.5 <= rate < 1.0)
        rate=0.6  
        
        #オーディオファイル読み込み
        s0,fs=sf.read(filename) 
        
        #信号が2ch以上の場合、1chの信号のみを使用する処理
        if min(s0.shape) < 255:
            s0 = s0[:,1]
            print("s0")
            print(type(s0))
            print(s0)

        #配列の作成
        s0 = np.array(s0)

        length_of_s0 = max(s0.shape)

        #出力信号の信号長を決定し、格納用変数を作成
        length_of_s1 = int(np.ceil(length_of_s0/rate)) 

        s1 = np.zeros((length_of_s1)) 
        
        template_size = int(np.floor(fs * 0.01))

        x = np.zeros((template_size)) 

        y = np.zeros((template_size)) 

        #基準の設定
        offset0 = 0 
        offset1 = 0 

        #0.005 → 5ms
        pmin = int(np.floor(fs * 0.005))

        #0.02 → 20ms        
        pmax = int(np.floor(fs * 0.02))

        r=np.zeros((pmax)) 
        
        while offset0 + pmax * 2 <= length_of_s0:
            
            x[0:template_size] = s0[offset0:offset0 + template_size] 

            max_of_r=0 
            p=pmin 
            for m in range(pmin-1,pmax):
                y[0:template_size] = s0[offset0 + m:offset0 + m + template_size] 
            
                r[m]=0 
                
                r[m]=np.sum(x[0:template_size] * y[0:template_size])     
                
                if r[m] > max_of_r:
                    max_of_r = r[m] 
                    p = m 
            
            s1[offset1:offset1 + p]=s0[offset0:offset0 + p]
            
            fadein = (p-np.arange(p))/p
            fadeout = np.arange(p)/p
        
            s1[offset1 + p:offset1 + p + p]=s0[offset0 + p:offset0 + p + p]*fadein
            s1[offset1 + p:offset1 + p + p]=s1[offset1 + p:offset1 + p + p]+s0[offset0:offset0 + p] * fadeout
        
            q = round(p * rate / (1 - rate)) 
        
            s1[offset1 + p + p:offset1 + p + q]=s0[offset0 + p:offset0+ q] 
            offset0=offset0 + q 
            offset1=offset1 + p + q 

        outname=input_dir + '\\output.wav'
        sf.write(outname,s1,fs) 
        
        # ファイル名(拡張子除く)を取得
        st = pathlib.PurePath(outname).stem

        # 変更後のファイル名の設定
        to_name = st + '.mp3'

        # ファイル名を変更する
        shutil.move(outname, input_dir + '\\' + to_name)

        input_movie = ffmpeg.input(input_dir + '\\' + change_speed + '_slow.mp4')

        input_music = ffmpeg.input(input_dir + '\\' + to_name)

        #出力ファイルの指定
        stream = ffmpeg.output(input_movie, input_music, output_dir + "\\" + change_speed + "_slow.MOV", vcodec="copy", acodec="copy")
        #実行
        ffmpeg.run(stream)

except Exception as e:
    print(e)

finally:

    #入力ファイルを空にする処理
    shutil.rmtree(input_dir)
    os.makedirs(input_dir)

    #処理時間の計測終了
    total = time.time() - start

    print("処理が完了しました。")
    print("処理時間:" + str(total) + "[sec]")
  • FPS:1秒間の動画が何枚の画像で構成されているかを示すの単位。
    Frames Per Secondの略で、フレームレートともいう。
  • スケールファクタ:速度変更の倍率。
  • フレーム:動画のもとになる静止画像の1コマ1コマ。
さすを
さすを

今回は、動画の速度を0.6倍に設定しました!

実行結果:

実行画面
実行画面
実行結果画面
実行結果画面

実際に速度を確認してみると、きちんと遅くなっていることが確認できます。

動画速度の比較
動画速度の比較

2本の動画(計1分35秒)のスロー動画を作成するのに約4分かかりました。

アプリを使っての編集が苦ではなく、かつ、自動化するよりも早く作成することができるのであれば、アプリを使う方がいいでしょう。

さすを
さすを

放っておけば自動でスロー動画を作成してくれるので、アプリを使って手作業でやるよりも楽ちんです!

万が一、エラーが出た場合、ターミナルにエラーログが出るようにしてあります。
また、outputフォルダにもとの動画を複製してあるので、途中で処理を中止しない限り、もとの動画が消えることはありません。

スポンサーリンク

2.Pythonスキルを伸ばす方法とは?

2-1.独学編

Pythonスキルを独学で身に着けるためには、参考書が必須です。

おすすめのPython書籍を以下の記事で解説したので、参考にしていただけたらと思います。

>>【レベル別&徹底解説】 Python書籍のおすすめ8選

本を買う前に、一度Pythonの学習をしてみたいという方は、Pythonを学べるおすすめ学習サイトを以下の記事で解説したので、こちらも参考にしてみてください。

>>【料金別&徹底解説】 Pythonおすすめ勉強サイト8選【楽しく学ぼう】

2-2.スクール編

お金がかかってもいいから、少しでも早くPythonスキルを身につけたい方は、TechAcademy(テックアカデミー)のPythonコースがおすすめです。

エンジニアになれば、受講料は1か月もあれば回収できるので、問題なしです。

本気でPythonスキルを身につけたい方は、スクールで一気にスキルを身に着けるのもありでしょう。

>>TechAcademy(テックアカデミー)のPythonコースはこちら

3.まとめ

3.まとめ

6,000万のPython案件に携わった経験のある筆者が、Pythonを使って音を残しながら動画の速度を遅くする方法を紹介してきました。

Pythonには便利なライブラリがありますが、画像だけ編集できるものや、音声だけ編集できるものが多く、まとめて編集することは難しかったりします。

この記事が少しでもあなたの役に立てていたらうれしいです。

動画編集の自動化をして、生まれた時間でさらに充実した日々をすごしましょう!

頑張るあなたを応援しています!

それでは!

>>【無料】Pythonでできること9選【初心者でも稼げます】

>>【初心者向け】Python学習の始め方【現役エンジニアがわかりやすく解説】

>>【徹底解説】Pythonエンジニアに転職する方法【失敗しない方法を詳しく解説】

>>【画像を使ってわかりやすく解説!】Pythonを使って自動でメール送信する方法【gmail編】

コメント

タイトルとURLをコピーしました