Added more notes and example scripts
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 5.3 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 282 KiB |
@@ -4,8 +4,8 @@ import java.io.File;
|
|||||||
|
|
||||||
|
|
||||||
public class SelectDir {
|
public class SelectDir {
|
||||||
private final Stage dirOpenerStage = new Stage();
|
private final Stage dirOpenerStage = new Stage();
|
||||||
private DirectoryChooser folderChooser = new DirectoryChooser();
|
private DirectoryChooser folderChooser = new DirectoryChooser();
|
||||||
private File selectedDir;
|
private File selectedDir;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import java.io.File;
|
|||||||
|
|
||||||
public class SelectFile {
|
public class SelectFile {
|
||||||
private final Stage fileOpenerStage = new Stage();
|
private final Stage fileOpenerStage = new Stage();
|
||||||
private FileChooser fileChooser = new FileChooser();
|
private FileChooser fileChooser = new FileChooser();
|
||||||
private File selectedFile;
|
private File selectedFile;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,38 @@
|
|||||||
|
Dependencies:
|
||||||
|
sudo pacman -S linux linux-headers
|
||||||
|
sudo pacman -S v4l2loopback-dkms v4l-utils ffmpeg python python-pip
|
||||||
|
# linux-headers needed for dkms build
|
||||||
|
|
||||||
|
pip install opencv-python
|
||||||
|
|
||||||
|
sudo dkms autoinstall
|
||||||
|
|
||||||
|
|
||||||
|
Load Module:
|
||||||
|
sudo modprobe v4l2loopback \
|
||||||
|
video_nr=10 \
|
||||||
|
card_label="Python Virtual Camera" \
|
||||||
|
exclusive_caps=1
|
||||||
|
|
||||||
|
|
||||||
|
Verify:
|
||||||
|
v4l2-ctl --list-devices
|
||||||
|
or
|
||||||
|
v4l2-ctl --list-formats-ext -d /dev/video10
|
||||||
|
or
|
||||||
|
mpv av://v4l2:/dev/video10
|
||||||
|
or
|
||||||
|
ffplay /dev/video10
|
||||||
|
|
||||||
|
|
||||||
|
Streaming to Device:
|
||||||
|
ffmpeg -re -loop 1 -i ~/<path to picture> \
|
||||||
|
-vf "format=yuv420p" \
|
||||||
|
-f v4l2 /dev/video10
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
<run script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
|
||||||
|
# Python imports
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
import cv2
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DEVICE = "/dev/video10"
|
||||||
|
WIDTH = 1280
|
||||||
|
HEIGHT = 720
|
||||||
|
FPS = 30
|
||||||
|
RESOLUTION = (WIDTH, HEIGHT)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def show_stream():
|
||||||
|
cap = cv2.VideoCapture(0)
|
||||||
|
|
||||||
|
cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH)
|
||||||
|
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT)
|
||||||
|
cap.set(cv2.CAP_PROP_FPS, FPS)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
ok, frame = cap.read()
|
||||||
|
|
||||||
|
if not ok: break
|
||||||
|
|
||||||
|
frame = cv2.resize(frame, RESOLUTION)
|
||||||
|
|
||||||
|
cv2.imshow("source", frame)
|
||||||
|
if cv2.waitKey(1) == 27:
|
||||||
|
break
|
||||||
|
|
||||||
|
cap.release()
|
||||||
|
cv2.destroyAllWindows()
|
||||||
|
|
||||||
|
|
||||||
|
def run_stream_ffmpeg():
|
||||||
|
image = cv2.imread("89538.jpg")
|
||||||
|
|
||||||
|
if image is None:
|
||||||
|
raise RuntimeError("Could not open image")
|
||||||
|
|
||||||
|
cmd = [
|
||||||
|
"ffmpeg",
|
||||||
|
"-loglevel", "error",
|
||||||
|
"-re",
|
||||||
|
"-f", "rawvideo",
|
||||||
|
"-pix_fmt", "bgr24",
|
||||||
|
"-s", f"{WIDTH}x{HEIGHT}",
|
||||||
|
"-r", f"{FPS}",
|
||||||
|
"-i", "-",
|
||||||
|
"-f", "v4l2",
|
||||||
|
"-pix_fmt", "yuv420p",
|
||||||
|
DEVICE,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Match the desired virtual-camera resolution
|
||||||
|
image = cv2.resize(image, RESOLUTION)
|
||||||
|
proc = subprocess.Popen(cmd, stdin = subprocess.PIPE)
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
proc.stdin.write( image.tobytes() )
|
||||||
|
time.sleep(1 / FPS)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
...
|
||||||
|
|
||||||
|
finally:
|
||||||
|
proc.stdin.close()
|
||||||
|
proc.wait()
|
||||||
|
|
||||||
|
|
||||||
|
def run_stream_opencv():
|
||||||
|
image = cv2.imread("89538.jpg")
|
||||||
|
|
||||||
|
if image is None:
|
||||||
|
raise RuntimeError("Could not open image")
|
||||||
|
|
||||||
|
# Match the desired virtual-camera resolution
|
||||||
|
image = cv2.resize(image, RESOLUTION)
|
||||||
|
writer = cv2.VideoWriter(
|
||||||
|
DEVICE,
|
||||||
|
cv2.VideoWriter_fourcc(*"YUYV"),
|
||||||
|
FPS,
|
||||||
|
RESOLUTION,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not writer.isOpened():
|
||||||
|
raise RuntimeError(f"Could not open {DEVICE}")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
writer.write(image)
|
||||||
|
|
||||||
|
time.sleep(1 / 30)
|
||||||
|
|
||||||
|
writer.release()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# show_stream()
|
||||||
|
# run_stream_opencv()
|
||||||
|
run_stream_ffmpeg()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
######################################################################
|
||||||
|
#Copyright (C) 2025 Kris Occhipinti
|
||||||
|
#https://filmsbykris.com
|
||||||
|
|
||||||
|
#This program is free software: you can redistribute it and/or modify
|
||||||
|
#it under the terms of the GNU General Public License as published by
|
||||||
|
#the Free Software Foundation version 3 of the License.
|
||||||
|
|
||||||
|
#This program is distributed in the hope that it will be useful,
|
||||||
|
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
#GNU General Public License for more details.
|
||||||
|
|
||||||
|
#You should have received a copy of the GNU General Public License
|
||||||
|
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
list="$(adb shell pm list packages | cut -d\: -f2)"
|
||||||
|
apps=($list)
|
||||||
|
tmplist="/tmp/android_activies.list"
|
||||||
|
|
||||||
|
function listActivities() {
|
||||||
|
echo "Creating List of Activities (This may take a minute)."
|
||||||
|
for app in "${apps[@]}"; do
|
||||||
|
adb shell dumpsys package "${app}" | grep -Eo "^[[:space:]]+[0-9a-f]+[[:space:]]+${app}/[^[:space:]]+" | grep -oE "[^[:space:]]+$"
|
||||||
|
done >"{$tmplist}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectActivity() {
|
||||||
|
activity="$(cat "{$tmplist}" | fzf --prompt="Select an Activity to Start: ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -f "${tmplist}" ]] || listActivities
|
||||||
|
|
||||||
|
selectActivity()
|
||||||
|
[[ $activity ]] && adb shell am start "{$activity}"
|
||||||
Reference in New Issue
Block a user