mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-19 01:17:06 +03:00
Add config option for handling HEVC playback on Apple devices
This commit is contained in:
parent
05f9ae50b5
commit
7362771d0c
@ -167,7 +167,7 @@ class CameraConfig(FrigateBaseModel):
|
|||||||
record_args = get_ffmpeg_arg_list(
|
record_args = get_ffmpeg_arg_list(
|
||||||
parse_preset_output_record(
|
parse_preset_output_record(
|
||||||
self.ffmpeg.output_args.record,
|
self.ffmpeg.output_args.record,
|
||||||
self.ffmpeg.output_args._force_record_hvc1,
|
self.ffmpeg.apple_compatibility,
|
||||||
)
|
)
|
||||||
or self.ffmpeg.output_args.record
|
or self.ffmpeg.output_args.record
|
||||||
)
|
)
|
||||||
|
|||||||
@ -42,7 +42,6 @@ class FfmpegOutputArgsConfig(FrigateBaseModel):
|
|||||||
default=RECORD_FFMPEG_OUTPUT_ARGS_DEFAULT,
|
default=RECORD_FFMPEG_OUTPUT_ARGS_DEFAULT,
|
||||||
title="Record role FFmpeg output arguments.",
|
title="Record role FFmpeg output arguments.",
|
||||||
)
|
)
|
||||||
_force_record_hvc1: bool = PrivateAttr(default=False)
|
|
||||||
|
|
||||||
|
|
||||||
class FfmpegConfig(FrigateBaseModel):
|
class FfmpegConfig(FrigateBaseModel):
|
||||||
@ -64,6 +63,10 @@ class FfmpegConfig(FrigateBaseModel):
|
|||||||
default=10.0,
|
default=10.0,
|
||||||
title="Time in seconds to wait before FFmpeg retries connecting to the camera.",
|
title="Time in seconds to wait before FFmpeg retries connecting to the camera.",
|
||||||
)
|
)
|
||||||
|
apple_compatibility: bool = Field(
|
||||||
|
default=False,
|
||||||
|
title="Set tag on HEVC (H.265) recording stream to improve compatibility with Apple players.",
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ffmpeg_path(self) -> str:
|
def ffmpeg_path(self) -> str:
|
||||||
|
|||||||
@ -458,13 +458,12 @@ class FrigateConfig(FrigateBaseModel):
|
|||||||
camera_config.ffmpeg.hwaccel_args = self.ffmpeg.hwaccel_args
|
camera_config.ffmpeg.hwaccel_args = self.ffmpeg.hwaccel_args
|
||||||
|
|
||||||
for input in camera_config.ffmpeg.inputs:
|
for input in camera_config.ffmpeg.inputs:
|
||||||
need_record_fourcc = False and "record" in input.roles
|
|
||||||
need_detect_dimensions = "detect" in input.roles and (
|
need_detect_dimensions = "detect" in input.roles and (
|
||||||
camera_config.detect.height is None
|
camera_config.detect.height is None
|
||||||
or camera_config.detect.width is None
|
or camera_config.detect.width is None
|
||||||
)
|
)
|
||||||
|
|
||||||
if need_detect_dimensions or need_record_fourcc:
|
if need_detect_dimensions:
|
||||||
stream_info = {"width": 0, "height": 0, "fourcc": None}
|
stream_info = {"width": 0, "height": 0, "fourcc": None}
|
||||||
try:
|
try:
|
||||||
stream_info = stream_info_retriever.get_stream_info(
|
stream_info = stream_info_retriever.get_stream_info(
|
||||||
@ -488,14 +487,6 @@ class FrigateConfig(FrigateBaseModel):
|
|||||||
else DEFAULT_DETECT_DIMENSIONS["height"]
|
else DEFAULT_DETECT_DIMENSIONS["height"]
|
||||||
)
|
)
|
||||||
|
|
||||||
if need_record_fourcc:
|
|
||||||
# Apple only supports HEVC if it is hvc1 (vs. hev1)
|
|
||||||
camera_config.ffmpeg.output_args._force_record_hvc1 = (
|
|
||||||
stream_info["fourcc"] == "hevc"
|
|
||||||
if stream_info.get("hevc")
|
|
||||||
else False
|
|
||||||
)
|
|
||||||
|
|
||||||
# Warn if detect fps > 10
|
# Warn if detect fps > 10
|
||||||
if camera_config.detect.fps > 10:
|
if camera_config.detect.fps > 10:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
|||||||
@ -65,6 +65,7 @@ INCLUDED_FFMPEG_VERSIONS = ["7.0", "5.0"]
|
|||||||
FFMPEG_HWACCEL_NVIDIA = "preset-nvidia"
|
FFMPEG_HWACCEL_NVIDIA = "preset-nvidia"
|
||||||
FFMPEG_HWACCEL_VAAPI = "preset-vaapi"
|
FFMPEG_HWACCEL_VAAPI = "preset-vaapi"
|
||||||
FFMPEG_HWACCEL_VULKAN = "preset-vulkan"
|
FFMPEG_HWACCEL_VULKAN = "preset-vulkan"
|
||||||
|
FFMPEG_HVC1_ARGS = ["-tag:v", "hvc1"]
|
||||||
|
|
||||||
# Regex constants
|
# Regex constants
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from enum import Enum
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from frigate.const import (
|
from frigate.const import (
|
||||||
|
FFMPEG_HVC1_ARGS,
|
||||||
FFMPEG_HWACCEL_NVIDIA,
|
FFMPEG_HWACCEL_NVIDIA,
|
||||||
FFMPEG_HWACCEL_VAAPI,
|
FFMPEG_HWACCEL_VAAPI,
|
||||||
FFMPEG_HWACCEL_VULKAN,
|
FFMPEG_HWACCEL_VULKAN,
|
||||||
@ -497,6 +498,6 @@ def parse_preset_output_record(arg: Any, force_record_hvc1: bool) -> list[str]:
|
|||||||
|
|
||||||
if force_record_hvc1:
|
if force_record_hvc1:
|
||||||
# Apple only supports HEVC if it is hvc1 (vs. hev1)
|
# Apple only supports HEVC if it is hvc1 (vs. hev1)
|
||||||
preset += ["-tag:v", "hvc1"]
|
preset += FFMPEG_HVC1_ARGS
|
||||||
|
|
||||||
return preset
|
return preset
|
||||||
|
|||||||
@ -19,6 +19,7 @@ from frigate.const import (
|
|||||||
CACHE_DIR,
|
CACHE_DIR,
|
||||||
CLIPS_DIR,
|
CLIPS_DIR,
|
||||||
EXPORT_DIR,
|
EXPORT_DIR,
|
||||||
|
FFMPEG_HVC1_ARGS,
|
||||||
MAX_PLAYLIST_SECONDS,
|
MAX_PLAYLIST_SECONDS,
|
||||||
PREVIEW_FRAME_TYPE,
|
PREVIEW_FRAME_TYPE,
|
||||||
)
|
)
|
||||||
@ -219,7 +220,7 @@ class RecordingExporter(threading.Thread):
|
|||||||
|
|
||||||
if self.playback_factor == PlaybackFactorEnum.realtime:
|
if self.playback_factor == PlaybackFactorEnum.realtime:
|
||||||
ffmpeg_cmd = (
|
ffmpeg_cmd = (
|
||||||
f"{self.config.ffmpeg.ffmpeg_path} -hide_banner {ffmpeg_input} -c copy -movflags +faststart {video_path}"
|
f"{self.config.ffmpeg.ffmpeg_path} -hide_banner {ffmpeg_input} -c copy -movflags +faststart"
|
||||||
).split(" ")
|
).split(" ")
|
||||||
elif self.playback_factor == PlaybackFactorEnum.timelapse_25x:
|
elif self.playback_factor == PlaybackFactorEnum.timelapse_25x:
|
||||||
ffmpeg_cmd = (
|
ffmpeg_cmd = (
|
||||||
@ -227,11 +228,16 @@ class RecordingExporter(threading.Thread):
|
|||||||
self.config.ffmpeg.ffmpeg_path,
|
self.config.ffmpeg.ffmpeg_path,
|
||||||
self.config.ffmpeg.hwaccel_args,
|
self.config.ffmpeg.hwaccel_args,
|
||||||
f"-an {ffmpeg_input}",
|
f"-an {ffmpeg_input}",
|
||||||
f"{self.config.cameras[self.camera].record.export.timelapse_args} -movflags +faststart {video_path}",
|
f"{self.config.cameras[self.camera].record.export.timelapse_args} -movflags +faststart",
|
||||||
EncodeTypeEnum.timelapse,
|
EncodeTypeEnum.timelapse,
|
||||||
)
|
)
|
||||||
).split(" ")
|
).split(" ")
|
||||||
|
|
||||||
|
if self.config.ffmpeg.apple_compatibility:
|
||||||
|
ffmpeg_cmd += FFMPEG_HVC1_ARGS
|
||||||
|
|
||||||
|
ffmpeg_cmd.append(video_path)
|
||||||
|
|
||||||
return ffmpeg_cmd, playlist_lines
|
return ffmpeg_cmd, playlist_lines
|
||||||
|
|
||||||
def get_preview_export_command(self, video_path: str) -> list[str]:
|
def get_preview_export_command(self, video_path: str) -> list[str]:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user