Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 11, 2017 20:16:50

rzh
Зарегистрирован: 2017-06-11
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

непонятное поведение popen и ffmpeg

Нужна помощь со скриптом. Непонятное мне поведение модуля subprocess .
Составил скрипт:

 #!/usr/bin/python
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import MySQLdb
import datetime
import socket
import subprocess
import time
import shlex
import logging
import os
import sys
import threading
##########
def pic(p, i):
    arg = shlex.split('ffmpeg -t 5 -i '+p+i+'.mp4 -r 1 -f image2 -s 150x120 '+p+'img/'+i+'_%02d.jpg -hide_banner')
    subprocess.Popen(arg, shell=False, stderr=open('ff_err.txt','w+'), stdout=open('ff_out.txt','w+'))
    pass
################
path = os.path.dirname(os.path.abspath(sys.argv[0]))+"/"
logging.basicConfig(format = '[%(asctime)s] %(message)s', level = logging.DEBUG, filename = path+'motion.log')
logging.info('START')
GPIO.setmode(GPIO.BCM)
GPIO_PIR = 18    # Пин, куда подключен ПИР
GPIO.setup(GPIO_PIR,GPIO.IN) # Режим работы пина на вход
GPIO_LED = 23    # Пин, куда подключен светодиод сигнализации периода фиксации
GPIO.setup(GPIO_LED,GPIO.OUT) # Режим работы пина на выход
GPIO.output(GPIO_LED, False)  # Тушим светодиод сигнализации
proc = 0            # Объект запущенного процесса записи видео
Flag = 0             # Признак, что у нас период фиксации (1 - фиксация)
Current_State = 0    # Переменная для состояния PIRа
Period = 10            # Период фиксации в секундах
DeltaTime = datetime.timedelta(seconds=Period)    # Вычисление постоянной дельты на период фиксации
Uid = 0                # Uid записи
# Обновляем Id Записи из БД
con = MySQLdb.connect(host="localhost", user="user", passwd="1", db="info")
cur = con.cursor()
cur.execute("SELECT id FROM motion ORDER BY id DESC LIMIT 1")
row = cur.fetchone()
while row is not None:
    Uid = int(row[0])
    row = cur.fetchone()
cur.close()
con.close()
Uid = Uid + 1    # Увеличиваем Uid для следующей записи
#GPIO.cleanup()
try:
    while True :
        Current_State = GPIO.input(GPIO_PIR)    # Read PIR state
        if Current_State==1 or os.path.exists(path+'rec'): # PIR активен
            GPIO.output(GPIO_LED, True)
            EndTime = datetime.datetime.now() + DeltaTime    # Расчет времени окончания пириода фиксации
            if Flag==0:    # Начало периода фиксации
                logging.info('start record...')
                # Начинаем запись видео
                com = 'openRTSP -4 -P 3600 -F "/home/www/cam/'+str(Uid)+'_" "rtsp://192.168.0.10:554/user=admin&password=&channel=1&stream=0.sdp"'
                args = shlex.split(com)    # Разбор аргументов строки в массив
                proc = subprocess.Popen(args, shell=False, stderr=open('/dev/null', 'w')) # Запуск процесса
                
                GPIO.output(GPIO_LED, True)    # Зажигаем светодиод сигнализации
                Flag = 1
                BeginTime = datetime.datetime.now()
                if os.path.exists(path+'rec'):
                    os.remove(path+'rec')
        elif Current_State==0:
            if Flag==1:        # Признак периода фиксации установлен
                if datetime.datetime.now() >= EndTime:
                    # Время окончания периода фиксации прошло
                    logging.info('end record, save to db: %s', Uid)
                    proc.send_signal(1)    # Остановка записи
                    proc.wait()
                    Flag = 0
                    GPIO.output(GPIO_LED, False)    # Тушим светодиод сигнализации
                    con = MySQLdb.connect(host="localhost", user="user", passwd="1", db="info")
                    cur = con.cursor()
                    cur.execute("INSERT INTO motion(dtStart,dtEnd) VALUES (%s, %s)",(BeginTime, datetime.datetime.now()))
                    con.commit()
                    # Постобработка файла видео
                    pathvideo = '/home/www/cam/'
                    id = str(Uid)
                    if os.path.exists(pathvideo+id+'_-00000-03600.mp4'):
                        logging.info('file %s exist, rename', pathvideo+id+'_-00000-03600.mp4')
                        os.rename(pathvideo+id+'_-00000-03600.mp4', pathvideo+id+'.mp4')
                    th = threading.Thread(name='th1', target=pic, args=(pathvideo, id))
                    th.start()
                    Uid = Uid + 1    # Увеличиваем Uid для следующей записи
        # Wait for 10 milliseconds
        time.sleep(0.01)
except KeyboardInterrupt:
    GPIO.cleanup()
    logging.info( u'EXIT' )

Если скрипт запускать из консоли
python /home/pi/motion.py
, то все отрабатывает на ура. Сперва отрабатывает ‘openRTSP’ в subprocess.Popen. Потом запускается ffmpeg в потоке, результат его работы видно в процессах:


Но, если запустить скрипт в фоне:
python /home/pi/motion.py &
, то первый popen хорошо отрабатывает, а на втором popen (ffmpeg), скрипт зависает:

Причем, неважно где второй popen вызывать: в потоке или в основном скрипте.
Как правильно запустить ffmpeg, чтобы он не останавливал скрипт, который запускается в фоне?

Отредактировано rzh (Июнь 11, 2017 20:22:14)

Прикреплённый файлы:
attachment 2.png (8,7 KБ)

Офлайн

#2 Июнь 12, 2017 00:05:31

vic57
Зарегистрирован: 2015-07-07
Сообщения: 893
Репутация: +  126  -
Профиль   Отправить e-mail  

непонятное поведение popen и ffmpeg

Офлайн

#3 Июнь 12, 2017 12:37:30

rzh
Зарегистрирован: 2017-06-11
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

непонятное поведение popen и ffmpeg

Да как то питон понятнее, чем bash и C

Офлайн

#4 Июнь 12, 2017 20:29:20

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

непонятное поведение popen и ffmpeg

как вариант попробуйте shell=True



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#5 Июнь 21, 2017 18:12:26

rzh
Зарегистрирован: 2017-06-11
Сообщения: 3
Репутация: +  0  -
Профиль   Отправить e-mail  

непонятное поведение popen и ffmpeg

Shell=True
тоже не помогает.

Решил.
Снес ffmpeg, установил avconv. Сразу все заработало как надо, даже параметры запуска менять не пришлось. )

Всем спасибо!

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version