Skip to content

Commit

Permalink
Merge branch 'dev' into fastapi-poc
Browse files Browse the repository at this point in the history
  • Loading branch information
iursevla committed Sep 15, 2024
2 parents b87fc33 + c17524b commit aa82e56
Show file tree
Hide file tree
Showing 41 changed files with 574 additions and 187 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/post_create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ sudo chown -R "$(id -u):$(id -g)" /media/frigate
# When started as a service, LIBAVFORMAT_VERSION_MAJOR is defined in the
# s6 service file. For dev, where frigate is started from an interactive
# shell, we define it in .bashrc instead.
echo 'export LIBAVFORMAT_VERSION_MAJOR=$(ffmpeg -version | grep -Po "libavformat\W+\K\d+")' >> $HOME/.bashrc
echo 'export LIBAVFORMAT_VERSION_MAJOR=$(/usr/lib/ffmpeg/7.0/bin/ffmpeg -version | grep -Po "libavformat\W+\K\d+")' >> $HOME/.bashrc

make version

Expand Down
3 changes: 2 additions & 1 deletion docker/main/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ ENV ALLOW_RESET=True
# Disable tokenizer parallelism warning
ENV TOKENIZERS_PARALLELISM=true

ENV PATH="/usr/lib/btbn-ffmpeg/bin:/usr/local/go2rtc/bin:/usr/local/tempio/bin:/usr/local/nginx/sbin:${PATH}"
ENV PATH="/usr/local/go2rtc/bin:/usr/local/tempio/bin:/usr/local/nginx/sbin:${PATH}"
ENV LIBAVFORMAT_VERSION_MAJOR=60

# Install dependencies
RUN --mount=type=bind,source=docker/main/install_deps.sh,target=/deps/install_deps.sh \
Expand Down
32 changes: 22 additions & 10 deletions docker/main/install_deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,26 @@ apt-get -qq install --no-install-recommends --no-install-suggests -y \

# btbn-ffmpeg -> amd64
if [[ "${TARGETARCH}" == "amd64" ]]; then
mkdir -p /usr/lib/btbn-ffmpeg
wget -qO btbn-ffmpeg.tar.xz "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2024-09-04-18-56/ffmpeg-n7.0.2-15-g0458a86656-linux64-gpl-7.0.tar.xz"
tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/btbn-ffmpeg --strip-components 1
rm -rf btbn-ffmpeg.tar.xz /usr/lib/btbn-ffmpeg/doc /usr/lib/btbn-ffmpeg/bin/ffplay
mkdir -p /usr/lib/ffmpeg/5.0
mkdir -p /usr/lib/ffmpeg/7.0
wget -qO btbn-ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2022-07-31-12-37/ffmpeg-n5.1-2-g915ef932a3-linux64-gpl-5.1.tar.xz"
tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/5.0 --strip-components 1
rm -rf btbn-ffmpeg.tar.xz /usr/lib/ffmpeg/5.0/doc /usr/lib/ffmpeg/5.0/bin/ffplay
wget -qO btbn-ffmpeg.tar.xz "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2024-09-13-12-57/ffmpeg-n7.0.2-17-gf705bc5b73-linux64-gpl-7.0.tar.xz"
tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1
rm -rf btbn-ffmpeg.tar.xz /usr/lib/ffmpeg/7.0/doc /usr/lib/ffmpeg/7.0/bin/ffplay
fi

# ffmpeg -> arm64
if [[ "${TARGETARCH}" == "arm64" ]]; then
mkdir -p /usr/lib/btbn-ffmpeg
wget -qO btbn-ffmpeg.tar.xz "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2024-09-04-18-56/ffmpeg-n7.0.2-15-g0458a86656-linuxarm64-gpl-7.0.tar.xz"
tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/btbn-ffmpeg --strip-components 1
rm -rf btbn-ffmpeg.tar.xz /usr/lib/btbn-ffmpeg/doc /usr/lib/btbn-ffmpeg/bin/ffplay
mkdir -p /usr/lib/ffmpeg/5.0
mkdir -p /usr/lib/ffmpeg/7.0
wget -qO btbn-ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2022-07-31-12-37/ffmpeg-n5.1-2-g915ef932a3-linuxarm64-gpl-5.1.tar.xz"
tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/5.0 --strip-components 1
rm -rf btbn-ffmpeg.tar.xz /usr/lib/ffmpeg/5.0/doc /usr/lib/ffmpeg/5.0/bin/ffplay
wget -qO btbn-ffmpeg.tar.xz "https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2024-09-13-12-57/ffmpeg-n7.0.2-17-gf705bc5b73-linuxarm64-gpl-7.0.tar.xz"
tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1
rm -rf btbn-ffmpeg.tar.xz /usr/lib/ffmpeg/7.0/doc /usr/lib/ffmpeg/7.0/bin/ffplay
fi

# arch specific packages
Expand All @@ -59,11 +67,15 @@ if [[ "${TARGETARCH}" == "amd64" ]]; then
echo 'deb https://deb.debian.org/debian bookworm main contrib non-free' >/etc/apt/sources.list.d/debian-bookworm.list
apt-get -qq update
apt-get -qq install --no-install-recommends --no-install-suggests -y \
intel-opencl-icd \
mesa-va-drivers radeontop libva-drm2 intel-media-va-driver-non-free i965-va-driver libmfx1 intel-gpu-tools
intel-opencl-icd intel-media-va-driver-non-free i965-va-driver \
libmfx-gen1.2 libmfx1 onevpl-tools intel-gpu-tools \
libva-drm2 \
mesa-va-drivers radeontop

# something about this dependency requires it to be installed in a separate call rather than in the line above
apt-get -qq install --no-install-recommends --no-install-suggests -y \
i965-va-driver-shaders

rm -f /etc/apt/sources.list.d/debian-bookworm.list
fi

Expand Down
2 changes: 0 additions & 2 deletions docker/main/rootfs/etc/s6-overlay/s6-rc.d/frigate/run
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ function migrate_db_path() {

echo "[INFO] Preparing Frigate..."
migrate_db_path
export LIBAVFORMAT_VERSION_MAJOR=$(ffmpeg -version | grep -Po 'libavformat\W+\K\d+')

echo "[INFO] Starting Frigate..."

cd /opt/frigate || echo "[ERROR] Failed to change working directory to /opt/frigate"
Expand Down
2 changes: 0 additions & 2 deletions docker/main/rootfs/etc/s6-overlay/s6-rc.d/go2rtc/run
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ function get_ip_and_port_from_supervisor() {
export FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL="${ip_address}:${webrtc_port}"
}

export LIBAVFORMAT_VERSION_MAJOR=$(ffmpeg -version | grep -Po 'libavformat\W+\K\d+')

if [[ -f "/dev/shm/go2rtc.yaml" ]]; then
echo "[INFO] Removing stale config from last run..."
rm /dev/shm/go2rtc.yaml
Expand Down
32 changes: 25 additions & 7 deletions docker/main/rootfs/usr/local/go2rtc/create_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,34 @@
**FRIGATE_ENV_VARS
)

# ensure ffmpeg path is set correctly
path = config.get("ffmpeg", {}).get("path", "default")
if path == "default":
if int(os.getenv("", "59") or "59") >= 59:
ffmpeg_path = "/usr/lib/ffmpeg/7.0/bin/ffmpeg"
else:
ffmpeg_path = "ffmpeg"
elif path == "7.0":
ffmpeg_path = "/usr/lib/ffmpeg/7.0/bin/ffmpeg"
elif path == "5.0":
ffmpeg_path = "/usr/lib/ffmpeg/5.0/bin/ffmpeg"
else:
ffmpeg_path = f"{path}/bin/ffmpeg"

if go2rtc_config.get("ffmpeg") is None:
go2rtc_config["ffmpeg"] = {"bin": ffmpeg_path}
elif go2rtc_config["ffmpeg"].get("bin") is None:
go2rtc_config["ffmpeg"]["bin"] = ffmpeg_path

# need to replace ffmpeg command when using ffmpeg4
if int(os.environ["LIBAVFORMAT_VERSION_MAJOR"]) < 59:
if go2rtc_config.get("ffmpeg") is None:
go2rtc_config["ffmpeg"] = {
"rtsp": "-fflags nobuffer -flags low_delay -stimeout 5000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}"
}
elif go2rtc_config["ffmpeg"].get("rtsp") is None:
if int(os.environ.get("LIBAVFORMAT_VERSION_MAJOR", "59") or "59") < 59:
if go2rtc_config["ffmpeg"].get("rtsp") is None:
go2rtc_config["ffmpeg"]["rtsp"] = (
"-fflags nobuffer -flags low_delay -stimeout 5000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}"
)
else:
if go2rtc_config.get("ffmpeg") is None:
go2rtc_config["ffmpeg"] = {"path": ""}

for name in go2rtc_config.get("streams", {}):
stream = go2rtc_config["streams"][name]
Expand Down Expand Up @@ -145,7 +163,7 @@
birdseye: dict[str, any] = config.get("birdseye")

input = f"-f rawvideo -pix_fmt yuv420p -video_size {birdseye.get('width', 1280)}x{birdseye.get('height', 720)} -r 10 -i {BIRDSEYE_PIPE}"
ffmpeg_cmd = f"exec:{parse_preset_hardware_acceleration_encode(config.get('ffmpeg', {}).get('hwaccel_args'), input, '-rtsp_transport tcp -f rtsp {output}')}"
ffmpeg_cmd = f"exec:{parse_preset_hardware_acceleration_encode(ffmpeg_path, config.get('ffmpeg', {}).get('hwaccel_args'), input, '-rtsp_transport tcp -f rtsp {output}')}"

if go2rtc_config.get("streams"):
go2rtc_config["streams"]["birdseye"] = ffmpeg_cmd
Expand Down
2 changes: 2 additions & 0 deletions docker/rpi/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ RUN rm -rf /usr/lib/btbn-ffmpeg/
RUN --mount=type=bind,source=docker/rpi/install_deps.sh,target=/deps/install_deps.sh \
/deps/install_deps.sh

ENV LIBAVFORMAT_VERSION_MAJOR=58

WORKDIR /opt/frigate/
COPY --from=rootfs / /
6 changes: 3 additions & 3 deletions docs/docs/configuration/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,15 @@ listen [::]:5000 ipv6only=off;
### Custom ffmpeg build
Included with Frigate is a build of ffmpeg that works for the vast majority of users. However, there exists some hardware setups which have incompatibilities with the included build. In this case, a docker volume mapping can be used to overwrite the included ffmpeg build with an ffmpeg build that works for your specific hardware setup.
Included with Frigate is a build of ffmpeg that works for the vast majority of users. However, there exists some hardware setups which have incompatibilities with the included build. In this case, statically built ffmpeg binary can be downloaded to /config and used.
To do this:
1. Download your ffmpeg build and uncompress to a folder on the host (let's use `/home/appdata/frigate/custom-ffmpeg` for this example).
1. Download your ffmpeg build and uncompress to the Frigate config folder.
2. Update your docker-compose or docker CLI to include `'/home/appdata/frigate/custom-ffmpeg':'/usr/lib/btbn-ffmpeg':'ro'` in the volume mappings.
3. Restart Frigate and the custom version will be used if the mapping was done correctly.
NOTE: The folder that is mapped from the host needs to be the folder that contains `/bin`. So if the full structure is `/home/appdata/frigate/custom-ffmpeg/bin/ffmpeg` then `/home/appdata/frigate/custom-ffmpeg` needs to be mapped to `/usr/lib/btbn-ffmpeg`.
NOTE: The folder that is set for the config needs to be the folder that contains `/bin`. So if the full structure is `/home/appdata/frigate/custom-ffmpeg/bin/ffmpeg` then the `ffmpeg -> path` field should be `/config/custom-ffmpeg/bin`.
### Custom go2rtc version
Expand Down
4 changes: 4 additions & 0 deletions docs/docs/configuration/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ birdseye:
# Optional: ffmpeg configuration
# More information about presets at https://docs.frigate.video/configuration/ffmpeg_presets
ffmpeg:
# Optional: ffmpeg binry path (default: shown below)
# can also be set to `7.0` or `5.0` to specify one of the included versions
# or can be set to any path that holds `bin/ffmpeg` & `bin/ffprobe`
path: "default"
# Optional: global ffmpeg args (default: shown below)
global_args: -hide_banner -loglevel warning -threads 2
# Optional: global hwaccel args (default: auto detect)
Expand Down
2 changes: 1 addition & 1 deletion frigate/api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ def ffprobe():
output = []

for path in paths:
ffprobe = ffprobe_stream(path.strip())
ffprobe = ffprobe_stream(current_app.frigate_config.ffmpeg, path.strip())
output.append(
{
"return_code": ffprobe.returncode,
Expand Down
25 changes: 20 additions & 5 deletions frigate/api/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,21 @@ def events_explore():
.dicts()
)

events = query.iterator()
return jsonify(list(events))
events = list(query.iterator())

processed_events = [
{k: v for k, v in event.items() if k != "data"}
| {
"data": {
k: v
for k, v in event["data"].items()
if k in ["type", "score", "top_score", "description"]
}
}
for event in events
]

return jsonify(processed_events)


@EventBp.route("/event_ids")
Expand Down Expand Up @@ -507,9 +520,11 @@ def events_search():
events = [
{k: v for k, v in event.items() if k != "data"}
| {
k: v
for k, v in event["data"].items()
if k in ["type", "score", "top_score", "description"]
"data": {
k: v
for k, v in event["data"].items()
if k in ["type", "score", "top_score", "description"]
}
}
| {
"search_distance": results[event["id"]]["distance"],
Expand Down
25 changes: 18 additions & 7 deletions frigate/api/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from tzlocal import get_localzone_name
from werkzeug.utils import secure_filename

from frigate.config import FrigateConfig
from frigate.const import (
CACHE_DIR,
CLIPS_DIR,
Expand Down Expand Up @@ -216,9 +217,10 @@ def get_snapshot_from_recording(camera_name: str, frame_time: str, format: str):

height = request.args.get("height", type=int)
codec = "png" if format == "png" else "mjpeg"
config: FrigateConfig = current_app.frigate_config

image_data = get_image_from_recording(
recording.path, time_in_segment, codec, height
config.ffmpeg, recording.path, time_in_segment, codec, height
)

if not image_data:
Expand Down Expand Up @@ -273,9 +275,12 @@ def submit_recording_snapshot_to_plus(camera_name: str, frame_time: str):
)

try:
config: FrigateConfig = current_app.frigate_config
recording: Recordings = recording_query.get()
time_in_segment = frame_time - recording.start_time
image_data = get_image_from_recording(recording.path, time_in_segment, "png")
image_data = get_image_from_recording(
config.ffmpeg, recording.path, time_in_segment, "png"
)

if not image_data:
return make_response(
Expand Down Expand Up @@ -474,9 +479,11 @@ def recording_clip(camera_name, start_ts, end_ts):
file_name = secure_filename(file_name)
path = os.path.join(CLIPS_DIR, f"cache/{file_name}")

config: FrigateConfig = current_app.frigate_config

if not os.path.exists(path):
ffmpeg_cmd = [
"ffmpeg",
config.ffmpeg.ffmpeg_path,
"-hide_banner",
"-y",
"-protocol_whitelist",
Expand Down Expand Up @@ -1141,8 +1148,9 @@ def preview_gif(camera_name: str, start_ts, end_ts, max_cache_age=2592000):
diff = start_ts - preview.start_time
minutes = int(diff / 60)
seconds = int(diff % 60)
config: FrigateConfig = current_app.frigate_config
ffmpeg_cmd = [
"ffmpeg",
config.ffmpeg.ffmpeg_path,
"-hide_banner",
"-loglevel",
"warning",
Expand Down Expand Up @@ -1206,9 +1214,10 @@ def preview_gif(camera_name: str, start_ts, end_ts, max_cache_age=2592000):

last_file = selected_previews[-2]
selected_previews.append(last_file)
config: FrigateConfig = current_app.frigate_config

ffmpeg_cmd = [
"ffmpeg",
config.ffmpeg.ffmpeg_path,
"-hide_banner",
"-loglevel",
"warning",
Expand Down Expand Up @@ -1301,8 +1310,9 @@ def preview_mp4(camera_name: str, start_ts, end_ts, max_cache_age=604800):
diff = start_ts - preview.start_time
minutes = int(diff / 60)
seconds = int(diff % 60)
config: FrigateConfig = current_app.frigate_config
ffmpeg_cmd = [
"ffmpeg",
config.ffmpeg.ffmpeg_path,
"-hide_banner",
"-loglevel",
"warning",
Expand Down Expand Up @@ -1364,9 +1374,10 @@ def preview_mp4(camera_name: str, start_ts, end_ts, max_cache_age=604800):

last_file = selected_previews[-2]
selected_previews.append(last_file)
config: FrigateConfig = current_app.frigate_config

ffmpeg_cmd = [
"ffmpeg",
config.ffmpeg.ffmpeg_path,
"-hide_banner",
"-loglevel",
"warning",
Expand Down
12 changes: 12 additions & 0 deletions frigate/api/review.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ def review():
return jsonify([r for r in review])


@ReviewBp.route("/review/event/<id>")
def get_review_from_event(id: str):
try:
return model_to_dict(
ReviewSegment.get(
ReviewSegment.data["detections"].cast("text") % f'*"{id}"*'
)
)
except DoesNotExist:
return "Review item not found", 404


@ReviewBp.route("/review/<id>")
def get_review(id: str):
try:
Expand Down
2 changes: 1 addition & 1 deletion frigate/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ def check_db_data_migrations(self) -> None:
except PermissionError:
logger.error("Unable to write to /config to save export state")

migrate_exports(self.config.cameras.keys())
migrate_exports(self.config.ffmpeg, self.config.cameras.keys())

def init_external_event_processor(self) -> None:
self.external_event_processor = ExternalEventProcessor(self.config)
Expand Down
Loading

0 comments on commit aa82e56

Please sign in to comment.