Last active
August 7, 2024 17:34
-
-
Save baptx/7faaaf876ef38db040ce0e25bde41625 to your computer and use it in GitHub Desktop.
PinePhone video recording using ffmpeg with preview
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# PinePhone video recording using ffmpeg with preview | |
# Based on https://gitlab.com/Alaraajavamma/fastvideo | |
# Video recording requires a recent Linux kernel version like 6.6: https://forum.pine64.org/showthread.php?tid=16539&pid=122700#pid122700 | |
# The script is based on v4l2loopback (setup instructions can be found at the end of the script). | |
# Close the first preview window to start recording and close the second preview window to end recording. | |
# Video recording does not work when using rear camera if Megapixels was closed after switching to front camera (error "Not a video capture device", can be fixed by reopening Megapixels). | |
# | |
# For quick access, you can create a file like ~/.local/share/applications/megavideo.desktop with this content (without # at the beginnning of lines, adjust executable path if needed): | |
# [Desktop Entry] | |
# Name=MegaVideo | |
# Exec=/opt/megavideo/pinephone_record_with_preview_gui.sh | |
# Terminal=false | |
# Icon=camera-video | |
# Type=Application | |
# X-Purism-FormFactor=Workstation;Mobile; | |
# | |
# And this content in /opt/megavideo/pinephone_record_with_preview_gui.sh: | |
# yad --title="Video recording" --text="Camera preview will be displayed in a new window" --form --field="Open rear camera":fbtn "/opt/megavideo/pinephone_record_with_preview.sh" --field="Open front camera":fbtn "/opt/megavideo/pinephone_record_with_preview.sh front" --buttons-layout=center --button="Quit" | |
WIDTH=1280 | |
HEIGHT=720 | |
FPS=20 # using lower FPS to avoid crashing the phone for recording videos with preview (crashed with 24 FPS or above at around 2 minutes but did not crash with 20 FPS when recording more than 5 minutes) | |
# enable default profile, unmute microphone audio and set volume to 100% in case it was changed (for example with pavucontrol) | |
pactl set-card-profile 0 HiFi | |
amixer set Capture cap 100% | |
CAMERA="ov5640" | |
SECONDARY_CAMERA="gc2145" | |
if [ "$1" == "front" ]; then | |
CAMERA="gc2145" | |
SECONDARY_CAMERA="ov5640" | |
fi | |
MATCH="$(media-ctl -d1 -p | grep sun6i-csi)" | |
if [ "$MATCH" ]; then | |
DEVICE="1" | |
else | |
DEVICE="0" | |
fi | |
MAIN_SENSOR="$(media-ctl -d$DEVICE -p | awk '/: '"$CAMERA"'/ {print "\"" $4, $5 "\""}')" | |
SECONDARY_SENSOR="$(media-ctl -d$DEVICE -p | awk '/: '"$SECONDARY_CAMERA"'/ {print "\"" $4, $5 "\""}')" | |
VIDEO_SOURCE="$(media-ctl -d$DEVICE -p | awk '/\/dev\/video/ {print $NF}')" | |
media-ctl -d$DEVICE -l"$SECONDARY_SENSOR:0->1:0[0],$MAIN_SENSOR:0->1:0[1]" | |
media-ctl -d$DEVICE -V"$MAIN_SENSOR:0[fmt:UYVY8_2X8/${WIDTH}x${HEIGHT}@1/$FPS]" | |
# Use same date format as Megapixels app based on ISO 8601 | |
TIMENOW="VID"$(date +%Y%m%d%H%M%S) | |
# libx264 recording without preview | |
#ffmpeg -input_format yuv420p -s ${WIDTH}x${HEIGHT} -f video4linux2 -thread_queue_size 4096 -i $VIDEO_SOURCE -f pulse -thread_queue_size 256 -i alsa_input.platform-sound.HiFi__hw_PinePhone_0__source -c:a aac -c:v libx264 -preset ultrafast -qp 23 ~/Videos/$TIMENOW.mp4 | |
# mjpeg configuration (does not work for front camera: "No JPEG data found in image") | |
# https://www.reddit.com/r/PINE64official/comments/olyqor/how_i_record_video_on_my_pinephone_in_tolerable/ | |
# https://www.reddit.com/r/pinephone/comments/p7eg2c/video_recording_using_gstreamer_on_the_pinephone/ | |
#media-ctl -d$DEVICE --set-v4l2 "$MAIN_SENSOR:0[fmt:JPEG_1X8/${WIDTH}x${HEIGHT}@1/$FPS]" | |
#v4l2-ctl --device $VIDEO_SOURCE --set-fmt-video="width=$WIDTH,height=$HEIGHT,pixelformat=JPEG" | |
# mjpeg recording with preview | |
#ffmpeg -f v4l2 -framerate 30 -video_size ${WIDTH}x${HEIGHT} -input_format mjpeg -i $VIDEO_SOURCE -f pulse -i alsa_input.platform-sound.HiFi__hw_PinePhone_0__source -c:a pcm_s16le -c:v mjpeg -b:v 64000k ~/Videos/$TIMENOW.avi -map 0:v -vf "format=yuv420p" -f xv display | |
# attempt to rotate recording and preview did not work: https://raspberrypi.stackexchange.com/questions/111713/is-there-a-way-to-rotate-the-cameras-image-at-the-driver-level-not-processing/114253#114253 | |
#if [ "$2" == "portrait" ]; then | |
# v4l2-ctl --device $VIDEO_SOURCE --set-ctrl=rotate=90 | |
#fi | |
# libx264 recording with preview (delay in preview: https://superuser.com/questions/343586/how-to-display-and-capture-webcam-stream-at-the-same-time/1551806#1551806) | |
#ffmpeg -input_format yuv420p -s ${WIDTH}x${HEIGHT} -f video4linux2 -thread_queue_size 4096 -i $VIDEO_SOURCE -f pulse -thread_queue_size 256 -i alsa_input.platform-sound.HiFi__hw_PinePhone_0__source -c:a aac -c:v libx264 -preset ultrafast -qp 23 ~/Videos/$TIMENOW.mp4 -f xv display | |
# libx264 recording with preview (no delay in preview: https://askubuntu.com/questions/165727/is-it-possible-for-two-processes-to-access-the-webcam-at-the-same-time/1244152#1244152) | |
# modprobe commands with root password are not needed when adding "options v4l2loopback exclusive_caps=1 video_nr=4" in a file like /etc/modprobe.d/dkms.conf and "v4l2loopback" in /etc/modules-load.d/modules.conf or /etc/modules (https://unix.stackexchange.com/questions/680689/load-kernel-module-at-boot-time-with-options/680698#680698) | |
# use video_nr=4 if the first video device that does not exist yet is /dev/video4 and so on | |
quit() { | |
# don't kill the ffmpeg source PID after the sleep in case we want to record another video before the previous encoding has finished (not needed anymore) | |
pkill -nf "libx264 -preset ultrafast -fps_mode vfr $HOME/Videos/$TIMENOW.mp4" # kill the current ffmpeg recording process to avoid killing new recordings (-n parameter to match newest process ffmpeg instead of kgx terminal) | |
pkill -f 'rawvideo -pix_fmt yuv420p /dev/video4' | |
#killall ffmpeg | |
#killall yad # close GUI automatically to know when the recording is finished is not needed with the encoding preview since closing it ends the recording (killing all ffmpeg and yad processes is ok as long as you don't have others running at the same time) | |
#sudo modprobe -r v4l2loopback | |
} | |
recording() { | |
# use a terminal like kgx to see if there are ffmpeg errors after recording | |
# the parameter "-fps_mode vfr (which replaces deprecated parameter "-vsync vfr" https://superuser.com/questions/460332/how-do-set-output-framerate-same-as-source-in-ffmpeg/1514949#1514949) is used to avoid warning "more than 1000 frames duplicated", to avoid encoding delay and reduce file size (if 20 FPS was configured in the script, this parameter may result in an FPS of around 15 FPS but the video should be smooth enough) | |
# thread_queue_size for audio increased to 4096 (2048 and values below were not enough) due to error "Thread message queue blocking; consider raising the thread_queue_size option" that appeared sometimes for example when typing on a keyboard close to the microphone and moving the camera fast or walking (default value was 8) | |
# crf should be better than qp (crf default value is 23: https://trac.ffmpeg.org/wiki/Encode/H.264) | |
# https://stackoverflow.com/questions/40668616/whats-the-difference-with-crf-and-qp-in-ffmpeg | |
# https://www.reddit.com/r/AV1/comments/omflyh/using_libsvtav1_what_qp_value_is_considered/ | |
kgx -e ffmpeg -input_format yuv420p -s ${WIDTH}x${HEIGHT} -f video4linux2 -thread_queue_size 4096 -i /dev/video4 -f pulse -thread_queue_size 4096 -i alsa_input.platform-sound.HiFi__hw_PinePhone_0__source -c:a aac -c:v libx264 -preset ultrafast -fps_mode vfr ~/Videos/$TIMENOW.mp4 & | |
ffplay /dev/video4 | |
quit | |
} | |
#sudo modprobe -r v4l2loopback # can fix issue "Some buffers are still owned by the caller on close" | |
#sudo modprobe v4l2loopback exclusive_caps=1 video_nr=4 | |
ffmpeg -i $VIDEO_SOURCE -f v4l2 -codec:v rawvideo -pix_fmt yuv420p /dev/video4 & | |
#sleep 1 # avoid error "Not a video capture device" (does not seem needed anymore) | |
ffplay -vf "drawtext=text='Close window to start recording':fontcolor=white:fontsize=24:box=1:[email protected]:boxborderw=5:x=(w-text_w)/2:y=(h-text_h)/2" /dev/video4 # preview and start recording when the first preview window is closed (https://stackoverflow.com/questions/17623676/text-on-video-ffmpeg/17624103#17624103) | |
recording |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment