termux / termux-api-package

Termux package containing scripts to call functionality in Termux:API.
MIT License
1.04k stars 321 forks source link

Create termux-camera-record #144

Closed SDRausty closed 2 years ago

SDRausty commented 2 years ago

This script enables timelapse camera recording with motion detection on Termux.

https://github.com/termux/termux-api/issues/360 https://github.com/termux/termux-app/issues/981

ghost commented 2 years ago

This is not Termux:API wrapper, but rather a wrapper for ffmpeg and termux-camera-photo. If you wish to work on this, please implement a video recorder backend for Termux:API application first.

SDRausty commented 2 years ago

a wrapper for ffmpeg and termux-camera-photo

No. It is not a wrapper for termux-camera-photo. It uses termux-api not termux-camera-photo; Please see line 21 which calls termux-api:

"${PREFIX:-/data/data/com.termux/files/usr}"/libexec/termux-api CameraPhoto --es camera "$CAMID" --es file "$PWD/$FRAMENAME"

implement a video recorder backend for Termux:API application first.

Thank you for this information; Is there a simple way to do this on device in Termux, specifically Android 10+?

ghost commented 2 years ago

No. It is not a wrapper for termux-camera-photo. It uses termux-api not termux-camera-photo

Doesn't matter, idea is the same: it still uses Photo for making Video. Only from that side it is not eligible to be a part of termux-api scripts. It doesn't represent the video API but attempts to poorly implement it through ffmpeg and sequence of frames obtained through CameraPhoto.

Is there a simple way to do this on device in Termux, specifically Android 10+?

No, you will need to write a Java class that implements a simple video recorder. Considering the issues you have linked previously, possibly that besides recorder you will need to implement an option that will allow video streaming on selected port.

This would not be an easy task.

SDRausty commented 2 years ago

uses Photo for making Video. Only from that side it is not eligible

Please note the script name termux-camera-record not termux-video-record. Script wrapper termux-camera-record can take multiple camera shots, process them and make output for the user, currently in the form of a video, this is an enhancement, not a video API that attempts to poorly implement video. Continuous video is desired.

allow video streaming on selected port video recorder backend

I have worked with video recorder backends before, so I understand your goal. Tinkering can result in astounding real time. This BASH script is not a video recorder even though it produces video output as a final result at present. Its intent is to store camera output that the user can access later, and review the input from the cameras that are embedded in Android smartphones and similar.

sequence of frames

Correct, this pull request is an attempted enhancement to termux-camera-photo based on topics discussed in the linked issues. Unfortunantly, it is not a resolution for those issues.

SDRausty commented 2 years ago

This is termux-camera-record in its current form:

#!/usr/bin/env bash
## Example usage: 'cams.bash 0 255 16 2048 r 90 2'
## Loop example: 'while true ; do cams.bash ; done'
## Semantics: [camid [totalframes+1 [framespersecond [threshold [r[otate] [degrees [exitwait]]]]]]]
## Please run 'pkg install ffmpeg imagemagick termux-api' before running this script.  Also ensure that Termux-api is installed, which is available at this https://github.com/termux/termux-api/actions/workflows/debug_build.yml webpage.
## VLC APK can be downloaded from these https://www.videolan.org/vlc/download-android.html and https://get.videolan.org/vlc-android/3.3.4/ webpages.
## More options in addition to image checking and rotation can be added by editing this file at the magick rotation command;  The command line options for magick are listed at this https://imagemagick.org/script/command-line-options.php webpage.
## All arguments are listed below, including their default values;  If run with no arguments, the default values will be used:
set -eu
[[ -n "${1:-}" ]] && { [[ "${1//-}" = [\/]* ]] || [[ "${1//-}" = [?]* ]] || [[ "${1//-}" = [Hh]* ]] ; } && { printf '\e[1;32m%s\n' "Help for '${0##*/}':" && TSFILE="($(grep '##\ ' "$0"))" && printf '\e[0;32m%s\e[1;32m\n%s\n' "$(for HL in "${TSFILE[@]}" ; do sed -e "s/##/  /" <<< "$HL" | cut -f 2 ; done | cut -d\) -f1)" "Help for '${0##*/}': DONE" ; exit ; }
CAMID=${1:-2} ## [1] default 2:  One camera 0 1 2 3 4 5 6 7 id,
FRAMECTOT=${2:-11} ## [2] default 11:  Video frame count total + 1,
FRAMERATE=${3:-1} ## [3] default 1:  Video 0.5 1 2 4 8 16 32 frames per second rendered in the mpg file,
THRESHOLDSET=${4:-256} ## [4] default 256:  Byte difference 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 between last two picture frames taken;  Used for motion detection.  The greater the number, the lesser the motion sensitivity.  Camera resolution also affects argument four,
_CAMS_ () {
FRAMECOUNT=0
while [ "$FRAMECOUNT" -le "$FRAMECTOT" ]
do
FRAMENAME="$(printf '%s.%04d.jpg' "${PWD##*/}$CAMID" "$FRAMECOUNT")"
printf '\e[0;36m%s\n\e[0;36m%s\n' "IP $((FRAMECOUNT + 1))/$((FRAMECTOT + 1)) frame count: ${THRESHOLDSET:-} threshold set" "IC $CAMID camid taking picture $FRAMENAME"
sleep 0.0"$(shuf -i 101-420 -n 1)"
"${PREFIX:-/data/data/com.termux/files/usr}"/libexec/termux-api CameraPhoto --es camera "$CAMID" --es file "$PWD/$FRAMENAME"
_ISZERO_ "$@"
done
}
_CHECKMOTIONDIFF_() {
if [ "$FRAMECOUNT" -ne 0 ]
then
THRESHOLD="$((LASTZERO - ISZERO))"
THRESHOLD="${THRESHOLD//-}"
if [ "$THRESHOLD" -le "$THRESHOLDSET" ]
then
printf '\e[0;36m%s\n\e[0;36m%s\n' "ID $THRESHOLD threshold: deleting file $FRAMENAME" "IT frame $FRAMENAME: Threshold set to $THRESHOLDSET"
rm -f "$FRAMENAME"
else
printf '\e[1;32m%s\n' "IS $THRESHOLD threshold: saving file $FRAMENAME"
FRAMECOUNT="$((FRAMECOUNT + 1))"
fi
else
FRAMECOUNT="$((FRAMECOUNT + 1))"
fi
}
_ISZERO_ () {
if [ -n "${ISZERO:-}" ]
then
LASTZERO="$ISZERO"
fi
sleep 0.0"$(shuf -i 420-640 -n 1)"
ISZERO="$(find . -type f -name "$FRAMENAME" -printf "%s" || ls -al "$FRAMENAME" | awk '{print $5}')"
if [ "$ISZERO" -eq 0 ]
then
if [ "$FRAMECOUNT" -eq 0 ]                                                    then
printf '\e[1;31m%s\n\e[1;35m%s\n' "ER could not begin shoot: ERROR" "Please check for issues and run '${0##*/}' again: EXITING..."
rm -f "$FRAMENAME"
exit 1                                                                        else
printf '\e[0;31m%s\n' "ID deleting zero size file $FRAMENAME"                 rm -f "$FRAMENAME"                                                            fi
else                                                                          _CHECKMOTIONDIFF_
fi                                                                            _MAGICKCK_ "$@"                                                               }                                                                             _MAKEDIRS_ () {
        mkdir -p "${1}cam"                                                            cd "${1}cam"
}
_MAGICKCK_ () {
if [ -e "$FRAMENAME" ]                                                        then
printf '\e[0;36m%s' "IC checking file $FRAMENAME for errors: "                MAGICKCK="$(nice -n 20 magick identify "$FRAMENAME" 2>&1 ||:)"                if grep -i error <<< "$MAGICKCK"                                              then
rm -f "$FRAMENAME"                                                            FRAMECOUNT="$((FRAMECOUNT - 1))"                                              printf '\e[0;33m%s\n\e[0;36m%s\n\e[0;32m%s\n' "DONE" "ID deleted file $FRAMENAME: ERROR" "IR redoing file $FRAMENAME: ERROR"
else                                                                          printf '\e[0;32m%s\n' "DONE"
if [ -n "${5:-}" ]                                                            then                                                                          if [[ "${5//-}" = [Rr]* ]] ## [5] default no rotation:  R|r[otate]: useful for portrait orientation.  You can use R or r to activate rotation which is preset to 90° rotation.  The rotation option can also be applied as a 90° rotation preset in arguments 1 and 2 in which case their default values will become presets,
then
printf '\e[0;36m%s' "IR rotating file $FRAMENAME by ${6:-90}°: " ## [6] default 90°:  Enter desired picture rotation angle in digits if you do not want to use the 90° default rotation,                                                  nice -n 20 magick "$FRAMENAME" -rotate "${6:-90}" "$FRAMENAME".jpg
mv "$FRAMENAME".jpg "$FRAMENAME"
printf '\e[0;32m%s\n' "DONE"
fi
fi
fi
fi
}
_MEFFMPEG_ () {
VIDEOPREFIX="${FRAMENAME%%.*}."
TIMESTAMP="$(date +%Y%m%d%H%M%S)"
printf '\e[0;36m%s\n' "IM making $VIDEOPREFIX$TIMESTAMP.mp4: This job will complete in the background..." && nice -n 20 ffmpeg -framerate "$FRAMERATE" -i "$VIDEOPREFIX"%04d.jpg "$VIDEOPREFIX$TIMESTAMP".mp4 && { ls -al "$VIDEOPREFIX$TIMESTAMP".mp4 && printf '\e[0;32m%s\n' "IM done making $VIDEOPREFIX$TIMESTAMP.mp4: DONE" ; } || printf '\e[0;31m%s\n' "EM creating file $VIDEOPREFIX$TIMESTAMP.mp4: ERROR"
}
_MAKEDIRS_ "${1:-2}"
_CAMS_ "$@"
_MEFFMPEG_ &
sleep "${7:-2}" ## [7] default of two seconds:  Time before exit;  Program ffmpeg will continue to run on in the background until its job of producing an mp4 file ends.  This sleep is so the jpg files can be read by ffmpeg if this script is used within a loop as in the loop example.
# termux-camera-record EOF

Camera id 1 is intense; Please try this script and submit your opinion about the results NOT seeking fluid motion with sound passed through a port in 4K and beyond, but as a high resolution autonomous picture capturing instrument.

SDRausty commented 2 years ago

Expanding on function _MAGICKCK_ could add unreal potential to termux-camera-record; Do you agree?

SDRausty commented 2 years ago

autonomous picture capturing instrument

Light and proximity sensor implementations; What is the easiest way to have termux-camera-record pause when the device is in a pocket or when there is not enough light for the camera to take pictures?

ghost commented 2 years ago

Please note the script name termux-camera-record not termux-video-record.

Video is anway recorded with camera, isn't it? Yes, you can create it from the images, but that doesn't change anything. So don't play with words.

If you want to contribute, please make sure your changes do not contradict the project design. I understand that implementing video API through Java is difficult, but no one forces you to do so.

This BASH script is not a video recorder even though it produces video output as a final result at present. Its intent is to store camera output that the user can access later

Why you have linked issues (https://github.com/termux/termux-api/issues/360, https://github.com/termux/termux-app/issues/981) that require implementation realtime video? Your solution is not realtime and even not close to it. Framerate also suffers - I'm about delays between images and not about ffmpeg tricks.