Feat/webcam improvements (#838)
* Detect available webcams * Fix CI, Move webcam id dropdown to the sidebar, Disable warnings * Fix CI
This commit is contained in:
parent
aa60da7e9a
commit
df96eb51e7
@ -2,7 +2,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from typing import Deque, Generator, Optional
|
from typing import Deque, Generator, List, Optional
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import gradio
|
import gradio
|
||||||
@ -10,7 +10,7 @@ from tqdm import tqdm
|
|||||||
|
|
||||||
from facefusion import logger, state_manager, wording
|
from facefusion import logger, state_manager, wording
|
||||||
from facefusion.audio import create_empty_audio_frame
|
from facefusion.audio import create_empty_audio_frame
|
||||||
from facefusion.common_helper import is_windows
|
from facefusion.common_helper import get_first, is_windows
|
||||||
from facefusion.content_analyser import analyse_stream
|
from facefusion.content_analyser import analyse_stream
|
||||||
from facefusion.face_analyser import get_average_face, get_many_faces
|
from facefusion.face_analyser import get_average_face, get_many_faces
|
||||||
from facefusion.ffmpeg import open_ffmpeg
|
from facefusion.ffmpeg import open_ffmpeg
|
||||||
@ -27,14 +27,17 @@ WEBCAM_START_BUTTON : Optional[gradio.Button] = None
|
|||||||
WEBCAM_STOP_BUTTON : Optional[gradio.Button] = None
|
WEBCAM_STOP_BUTTON : Optional[gradio.Button] = None
|
||||||
|
|
||||||
|
|
||||||
def get_webcam_capture() -> Optional[cv2.VideoCapture]:
|
def get_webcam_capture(index : int) -> Optional[cv2.VideoCapture]:
|
||||||
global WEBCAM_CAPTURE
|
global WEBCAM_CAPTURE
|
||||||
|
|
||||||
if WEBCAM_CAPTURE is None:
|
if WEBCAM_CAPTURE is None:
|
||||||
|
cv2.setLogLevel(0)
|
||||||
if is_windows():
|
if is_windows():
|
||||||
webcam_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
|
webcam_capture = cv2.VideoCapture(index, cv2.CAP_DSHOW)
|
||||||
else:
|
else:
|
||||||
webcam_capture = cv2.VideoCapture(0)
|
webcam_capture = cv2.VideoCapture(index)
|
||||||
|
cv2.setLogLevel(3)
|
||||||
|
|
||||||
if webcam_capture and webcam_capture.isOpened():
|
if webcam_capture and webcam_capture.isOpened():
|
||||||
WEBCAM_CAPTURE = webcam_capture
|
WEBCAM_CAPTURE = webcam_capture
|
||||||
return WEBCAM_CAPTURE
|
return WEBCAM_CAPTURE
|
||||||
@ -68,31 +71,35 @@ def render() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def listen() -> None:
|
def listen() -> None:
|
||||||
|
webcam_device_id_dropdown = get_ui_component('webcam_device_id_dropdown')
|
||||||
webcam_mode_radio = get_ui_component('webcam_mode_radio')
|
webcam_mode_radio = get_ui_component('webcam_mode_radio')
|
||||||
webcam_resolution_dropdown = get_ui_component('webcam_resolution_dropdown')
|
webcam_resolution_dropdown = get_ui_component('webcam_resolution_dropdown')
|
||||||
webcam_fps_slider = get_ui_component('webcam_fps_slider')
|
webcam_fps_slider = get_ui_component('webcam_fps_slider')
|
||||||
source_image = get_ui_component('source_image')
|
source_image = get_ui_component('source_image')
|
||||||
|
|
||||||
if webcam_mode_radio and webcam_resolution_dropdown and webcam_fps_slider:
|
if webcam_device_id_dropdown and webcam_mode_radio and webcam_resolution_dropdown and webcam_fps_slider:
|
||||||
start_event = WEBCAM_START_BUTTON.click(start, inputs = [ webcam_mode_radio, webcam_resolution_dropdown, webcam_fps_slider ], outputs = WEBCAM_IMAGE)
|
start_event = WEBCAM_START_BUTTON.click(start, inputs = [ webcam_device_id_dropdown, webcam_mode_radio, webcam_resolution_dropdown, webcam_fps_slider ], outputs = WEBCAM_IMAGE)
|
||||||
WEBCAM_STOP_BUTTON.click(stop, cancels = start_event, outputs = WEBCAM_IMAGE)
|
WEBCAM_STOP_BUTTON.click(stop, cancels = start_event, outputs = WEBCAM_IMAGE)
|
||||||
|
|
||||||
if source_image:
|
if source_image:
|
||||||
source_image.change(stop, cancels = start_event, outputs = WEBCAM_IMAGE)
|
source_image.change(stop, cancels = start_event, outputs = WEBCAM_IMAGE)
|
||||||
|
|
||||||
|
|
||||||
def start(webcam_mode : WebcamMode, webcam_resolution : str, webcam_fps : Fps) -> Generator[VisionFrame, None, None]:
|
def start(webcam_device_id : int, webcam_mode : WebcamMode, webcam_resolution : str, webcam_fps : Fps) -> Generator[VisionFrame, None, None]:
|
||||||
state_manager.set_item('face_selector_mode', 'one')
|
state_manager.set_item('face_selector_mode', 'one')
|
||||||
source_image_paths = filter_image_paths(state_manager.get_item('source_paths'))
|
source_image_paths = filter_image_paths(state_manager.get_item('source_paths'))
|
||||||
source_frames = read_static_images(source_image_paths)
|
source_frames = read_static_images(source_image_paths)
|
||||||
source_faces = get_many_faces(source_frames)
|
source_faces = get_many_faces(source_frames)
|
||||||
source_face = get_average_face(source_faces)
|
source_face = get_average_face(source_faces)
|
||||||
stream = None
|
stream = None
|
||||||
|
webcam_capture = None
|
||||||
|
|
||||||
if webcam_mode in [ 'udp', 'v4l2' ]:
|
if webcam_mode in [ 'udp', 'v4l2' ]:
|
||||||
stream = open_stream(webcam_mode, webcam_resolution, webcam_fps) #type:ignore[arg-type]
|
stream = open_stream(webcam_mode, webcam_resolution, webcam_fps) #type:ignore[arg-type]
|
||||||
webcam_width, webcam_height = unpack_resolution(webcam_resolution)
|
webcam_width, webcam_height = unpack_resolution(webcam_resolution)
|
||||||
webcam_capture = get_webcam_capture()
|
|
||||||
|
if isinstance(webcam_device_id, int):
|
||||||
|
webcam_capture = get_webcam_capture(webcam_device_id)
|
||||||
|
|
||||||
if webcam_capture and webcam_capture.isOpened():
|
if webcam_capture and webcam_capture.isOpened():
|
||||||
webcam_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG')) #type:ignore[attr-defined]
|
webcam_capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG')) #type:ignore[attr-defined]
|
||||||
@ -163,9 +170,22 @@ def open_stream(stream_mode : StreamMode, stream_resolution : str, stream_fps :
|
|||||||
commands.extend([ '-b:v', '2000k', '-f', 'mpegts', 'udp://localhost:27000?pkt_size=1316' ])
|
commands.extend([ '-b:v', '2000k', '-f', 'mpegts', 'udp://localhost:27000?pkt_size=1316' ])
|
||||||
if stream_mode == 'v4l2':
|
if stream_mode == 'v4l2':
|
||||||
try:
|
try:
|
||||||
device_name = os.listdir('/sys/devices/virtual/video4linux')[0]
|
device_name = get_first(os.listdir('/sys/devices/virtual/video4linux'))
|
||||||
if device_name:
|
if device_name:
|
||||||
commands.extend([ '-f', 'v4l2', '/dev/' + device_name ])
|
commands.extend([ '-f', 'v4l2', '/dev/' + device_name ])
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
logger.error(wording.get('stream_not_loaded').format(stream_mode = stream_mode), __name__)
|
logger.error(wording.get('stream_not_loaded').format(stream_mode = stream_mode), __name__)
|
||||||
return open_ffmpeg(commands)
|
return open_ffmpeg(commands)
|
||||||
|
|
||||||
|
|
||||||
|
def get_available_webcam_ids(webcam_id_start : int, webcam_id_end : int) -> List[int]:
|
||||||
|
available_webcam_ids = []
|
||||||
|
|
||||||
|
for index in range(webcam_id_start, webcam_id_end):
|
||||||
|
webcam_capture = get_webcam_capture(index)
|
||||||
|
|
||||||
|
if webcam_capture and webcam_capture.isOpened():
|
||||||
|
available_webcam_ids.append(index)
|
||||||
|
clear_webcam_capture()
|
||||||
|
|
||||||
|
return available_webcam_ids
|
||||||
|
@ -3,19 +3,29 @@ from typing import Optional
|
|||||||
import gradio
|
import gradio
|
||||||
|
|
||||||
from facefusion import wording
|
from facefusion import wording
|
||||||
|
from facefusion.common_helper import get_first
|
||||||
from facefusion.uis import choices as uis_choices
|
from facefusion.uis import choices as uis_choices
|
||||||
|
from facefusion.uis.components.webcam import get_available_webcam_ids
|
||||||
from facefusion.uis.core import register_ui_component
|
from facefusion.uis.core import register_ui_component
|
||||||
|
|
||||||
|
WEBCAM_DEVICE_ID_DROPDOWN : Optional[gradio.Dropdown] = None
|
||||||
WEBCAM_MODE_RADIO : Optional[gradio.Radio] = None
|
WEBCAM_MODE_RADIO : Optional[gradio.Radio] = None
|
||||||
WEBCAM_RESOLUTION_DROPDOWN : Optional[gradio.Dropdown] = None
|
WEBCAM_RESOLUTION_DROPDOWN : Optional[gradio.Dropdown] = None
|
||||||
WEBCAM_FPS_SLIDER : Optional[gradio.Slider] = None
|
WEBCAM_FPS_SLIDER : Optional[gradio.Slider] = None
|
||||||
|
|
||||||
|
|
||||||
def render() -> None:
|
def render() -> None:
|
||||||
|
global WEBCAM_DEVICE_ID_DROPDOWN
|
||||||
global WEBCAM_MODE_RADIO
|
global WEBCAM_MODE_RADIO
|
||||||
global WEBCAM_RESOLUTION_DROPDOWN
|
global WEBCAM_RESOLUTION_DROPDOWN
|
||||||
global WEBCAM_FPS_SLIDER
|
global WEBCAM_FPS_SLIDER
|
||||||
|
|
||||||
|
available_webcam_ids = get_available_webcam_ids(0, 10) or [ 'none' ] #type:ignore[list-item]
|
||||||
|
WEBCAM_DEVICE_ID_DROPDOWN = gradio.Dropdown(
|
||||||
|
value = get_first(available_webcam_ids),
|
||||||
|
label = wording.get('uis.webcam_device_id_dropdown'),
|
||||||
|
choices = available_webcam_ids
|
||||||
|
)
|
||||||
WEBCAM_MODE_RADIO = gradio.Radio(
|
WEBCAM_MODE_RADIO = gradio.Radio(
|
||||||
label = wording.get('uis.webcam_mode_radio'),
|
label = wording.get('uis.webcam_mode_radio'),
|
||||||
choices = uis_choices.webcam_modes,
|
choices = uis_choices.webcam_modes,
|
||||||
@ -33,6 +43,7 @@ def render() -> None:
|
|||||||
minimum = 1,
|
minimum = 1,
|
||||||
maximum = 60
|
maximum = 60
|
||||||
)
|
)
|
||||||
|
register_ui_component('webcam_device_id_dropdown', WEBCAM_DEVICE_ID_DROPDOWN)
|
||||||
register_ui_component('webcam_mode_radio', WEBCAM_MODE_RADIO)
|
register_ui_component('webcam_mode_radio', WEBCAM_MODE_RADIO)
|
||||||
register_ui_component('webcam_resolution_dropdown', WEBCAM_RESOLUTION_DROPDOWN)
|
register_ui_component('webcam_resolution_dropdown', WEBCAM_RESOLUTION_DROPDOWN)
|
||||||
register_ui_component('webcam_fps_slider', WEBCAM_FPS_SLIDER)
|
register_ui_component('webcam_fps_slider', WEBCAM_FPS_SLIDER)
|
||||||
|
@ -73,6 +73,7 @@ ComponentName = Literal\
|
|||||||
'target_image',
|
'target_image',
|
||||||
'target_video',
|
'target_video',
|
||||||
'ui_workflow_dropdown',
|
'ui_workflow_dropdown',
|
||||||
|
'webcam_device_id_dropdown',
|
||||||
'webcam_fps_slider',
|
'webcam_fps_slider',
|
||||||
'webcam_mode_radio',
|
'webcam_mode_radio',
|
||||||
'webcam_resolution_dropdown'
|
'webcam_resolution_dropdown'
|
||||||
|
@ -330,6 +330,7 @@ WORDING : Dict[str, Any] =\
|
|||||||
'video_memory_strategy_dropdown': 'VIDEO MEMORY STRATEGY',
|
'video_memory_strategy_dropdown': 'VIDEO MEMORY STRATEGY',
|
||||||
'webcam_fps_slider': 'WEBCAM FPS',
|
'webcam_fps_slider': 'WEBCAM FPS',
|
||||||
'webcam_image': 'WEBCAM',
|
'webcam_image': 'WEBCAM',
|
||||||
|
'webcam_device_id_dropdown': 'WEBCAM DEVICE ID',
|
||||||
'webcam_mode_radio': 'WEBCAM MODE',
|
'webcam_mode_radio': 'WEBCAM MODE',
|
||||||
'webcam_resolution_dropdown': 'WEBCAM RESOLUTION'
|
'webcam_resolution_dropdown': 'WEBCAM RESOLUTION'
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user