본문 바로가기
Python

Pyinstaller ffmpeg 포함 시키기

by holy season 2023. 8. 12.
반응형

ffmpeg란?

  • FFmpeg는 영상 및 오디오 데이터를 다양한 형식으로 변환, 편집 및 스트리밍할 수 있는 오픈 소스 멀티미디어 프레임워크
  • FFmpeg은 다양한 플랫폼에서 작동
  • 비디오, 오디오, 이미지, 서브타이틀 등 다양한 멀티미디어 데이터를 처리할 수 있는 도구와 라이브러리의 집합

https://www.ffmpeg.org/

 

FFmpeg

Converting video and audio has never been so easy. $ ffmpeg -i input.mp4 output.avi     News May 31st, 2023, Vulkan decoding A few days ago, Vulkan-powered decoding hardware acceleration code was merged into the codebase. This is the first vendor-generic

www.ffmpeg.org

Pyinstaller ffmpeg.exe 파일 추가하기

pyinstaller로 fffmpeg.exe를 추가하고 싶다면 다음과 같은 옵션을 사용해서 추가하면 된다.

pyinstaller -F --add-binary "[실행파일 경로];[실행파일을 넣을 폴더]" [배포할 파이썬 파일]

예제(ffmpeg rtsp 영상 저장, ffplay rtsp 영상 재생)

다음 밑에 코드는 rtsp 영상 주소를 이용하여 ffmpeg로 영상을 저장하고 ffplay로 영상을 재생하는 코드이다.

현재 경로는 bin폴더에 있는 ffmpeg.exe, ffplay.exe파일의 경로를 지정하여 영상을 저장하고 실행한다.

import subprocess
import os
import os.path
import threading

if __name__ == '__main__' :
    # ffmpeg.exe 경로
    ffmpegPath = os.getcwd()
    ffmpegPath = os.path.join(ffmpegPath, 'bin', 'ffmpeg.exe')

    # rtsp 영상 주소
    rtspSource = 'rtsp://210.99.70.120:1935/live/cctv001.stream'

    # 저장할 위치
    outputPath = os.getcwd()
    outputPath = os.path.join(outputPath, 'output.mp4')

    # ffmpeg 명령어
    ffmpegCommand = f'{ffmpegPath} -rtsp_transport tcp -i {rtspSource} -r 10 -t 3600 -c:v libx264 -vcodec copy -acodec copy -y {outputPath}'

    # ffmpeg 실행
    ffmpegThread = threading.Thread(target=subprocess.call, args=(ffmpegCommand,))
    ffmpegThread.start()

    # ffplay 명령어
    ffplayPath = os.getcwd()
    ffplayPath = os.path.join(ffplayPath, 'bin', 'ffplay.exe')
    ffplayCommand = f'{ffplayPath} -rtsp_transport tcp {rtspSource}' 

    # ffplay 실행
    ffplayThread = threading.Thread(target=subprocess.call, args=(ffplayCommand,))
    ffplayThread.start()

예제 파일 pyinstaller 생성

위에 있는 예제 파일을 다음과 같은 명령어를 사용하여 exe파일로 만들고 실행하면 다음과 같은 오류가 나타나게 된다.

pyinstaller -F --add-binary "bin/*;bin/" main.py

이 오류는 현재 실행하고 있는 폴더에서 ffmpeg.exe, ffplay.exe경로를 찾을 수 없어서 나타나는 오류이다.

해결 방안

import로 sys를 가져오고 _MEIPASS가 있는지 확인해서 개발 경로와 exe 배포파일 경로를 분리한다.

경로 설정

    # ffmpeg.exe, ffplay.exe 경로 설정
    if hasattr(sys, "_MEIPASS"):
        ffmpegPath = os.path.join(sys._MEIPASS, 'bin', "ffmpeg.exe")
        ffplayPath = os.path.join(sys._MEIPASS, 'bin', 'ffplay.exe')
    else:
        ffmpegPath = os.path.join(os.getcwd(), "bin", "ffmpeg.exe")
        ffplayPath = os.path.join(os.getcwd(), "bin", "ffplay.exe")

전체 코드

import subprocess
import os
import os.path
import threading
import sys

if __name__ == '__main__' :

    # ffmpeg.exe, ffplay.exe 경로 설정
    if hasattr(sys, "_MEIPASS"):
        ffmpegPath = os.path.join(sys._MEIPASS, 'bin', "ffmpeg.exe")
        ffplayPath = os.path.join(sys._MEIPASS, 'bin', 'ffplay.exe')
    else:
        ffmpegPath = os.path.join(os.getcwd(), "bin", "ffmpeg.exe")
        ffplayPath = os.path.join(os.getcwd(), "bin", "ffplay.exe")


    # rtsp 영상 주소
    rtspSource = 'rtsp://210.99.70.120:1935/live/cctv001.stream'

    # 저장할 위치
    outputPath = os.getcwd()
    outputPath = os.path.join(outputPath, 'output.mp4')

    # ffmpeg 명령어
    ffmpegCommand = f'{ffmpegPath} -rtsp_transport tcp -i {rtspSource} -r 10 -t 3600 -c:v libx264 -vcodec copy -acodec copy -y {outputPath}'

    # ffmpeg 실행
    ffmpegThread = threading.Thread(target=subprocess.call, args=(ffmpegCommand,))
    ffmpegThread.start()

    # ffplay 명령어

    ffplayCommand = f'{ffplayPath} -rtsp_transport tcp {rtspSource}' 

    # ffplay 실행
    ffplayThread = threading.Thread(target=subprocess.call, args=(ffplayCommand,))
    ffplayThread.start()

위에 코드를 추가한 후 pyinstaller 명령어로 다시 exe파일을 생성하고 실행하면 ffmpeg.exe, ffplay.exe 개발환경과 배포 환경에서 실행시 경로를 잘 찾아주어서 실행이 정삭적으로 되게 된다.

pyinstaller -F --add-binary "bin/*;bin/" main.py

실행 화면

ffplay 실행 화면
ffmpeg 실행 화면
폴더 구조

반응형

'Python' 카테고리의 다른 글

파이썬 로깅 사용하기  (0) 2023.08.26
openCV를 이용한 PySide 영상 출력  (0) 2023.08.16
아나콘다(Anaconda)  (0) 2023.08.09
TTS 사용하기  (0) 2023.08.08
PySide6 Qtdesigner로 만든 UI를 파이썬 파일로 만들기  (0) 2023.07.12