{
  lib,
  config,
  pkgs,
  ...
}:
with lib;
let
  cfg = config.webcam-rtsp;

  effectiveStreams =
    if cfg.streams != { } then
      cfg.streams
    else
      {
        main = {
          device = cfg.device;
          rtspUrl = cfg.rtspUrl;
          framerate = cfg.framerate;
          videoSize = cfg.videoSize;
          preset = cfg.preset;
          bitrateKbps = cfg.bitrateKbps;
          maxrateKbps = cfg.maxrateKbps;
          bufsizeKbps = cfg.bufsizeKbps;
          useVaapi = cfg.useVaapi;
          vaapiDevice = cfg.vaapiDevice;
          vaapiQp = cfg.vaapiQp;
          vaapiDriver = cfg.vaapiDriver;
        };
      };

  sanitizeName = name: replaceStrings [ "/" " " ] [ "-" "-" ] name;
in
{
  options = {
    webcam-rtsp = {
      enable = mkEnableOption "enables webcam RTSP publisher";
      device = mkOption {
        type = types.str;
        default = "/dev/v4l/by-id/usb-GENERAL_GENERAL_WEBCAM-video-index0";
        description = "V4L2 device used as input for ffmpeg.";
      };
      rtspUrl = mkOption {
        type = types.str;
        default = "rtsp://192.168.1.143:8554/laptop";
        description = "Destination RTSP URL where ffmpeg publishes the stream.";
      };
      framerate = mkOption {
        type = types.int;
        default = 30;
        description = "Input framerate for the webcam stream.";
      };
      videoSize = mkOption {
        type = types.str;
        default = "1280x720";
        description = "Input video size for the webcam stream.";
      };
      preset = mkOption {
        type = types.enum [
          "ultrafast"
          "superfast"
          "veryfast"
          "faster"
          "fast"
          "medium"
          "slow"
          "slower"
          "veryslow"
        ];
        default = "veryfast";
        description = "x264 preset used for software encoding.";
      };
      bitrateKbps = mkOption {
        type = types.nullOr types.int;
        default = null;
        description = "Target bitrate in kbps. Set to null for CRF-like unconstrained output.";
      };
      maxrateKbps = mkOption {
        type = types.nullOr types.int;
        default = null;
        description = "Maximum bitrate in kbps. Defaults to bitrateKbps when unset.";
      };
      bufsizeKbps = mkOption {
        type = types.nullOr types.int;
        default = null;
        description = "Rate-control buffer in kbps. Defaults to 2x bitrateKbps when unset.";
      };
      useVaapi = mkOption {
        type = types.bool;
        default = false;
        description = "Use VAAPI hardware encoding (h264_vaapi) instead of libx264.";
      };
      vaapiDevice = mkOption {
        type = types.str;
        default = "/dev/dri/renderD128";
        description = "VAAPI render device path used when useVaapi = true.";
      };
      vaapiQp = mkOption {
        type = types.int;
        default = 24;
        description = "VAAPI quality parameter (lower means better quality, higher CPU/bitrate).";
      };
      vaapiDriver = mkOption {
        type = types.nullOr types.str;
        default = null;
        description = "Optional LIBVA_DRIVER_NAME value (for example iHD).";
      };
      streams = mkOption {
        type = types.attrsOf (
          types.submodule {
            options = {
              device = mkOption {
                type = types.str;
                description = "V4L2 device used as input for ffmpeg.";
              };
              rtspUrl = mkOption {
                type = types.str;
                description = "Destination RTSP URL where ffmpeg publishes the stream.";
              };
              framerate = mkOption {
                type = types.int;
                default = 30;
                description = "Input framerate for this stream.";
              };
              videoSize = mkOption {
                type = types.str;
                default = "1280x720";
                description = "Input video size for this stream.";
              };
              preset = mkOption {
                type = types.enum [
                  "ultrafast"
                  "superfast"
                  "veryfast"
                  "faster"
                  "fast"
                  "medium"
                  "slow"
                  "slower"
                  "veryslow"
                ];
                default = "veryfast";
                description = "x264 preset used for software encoding.";
              };
              bitrateKbps = mkOption {
                type = types.nullOr types.int;
                default = null;
                description = "Target bitrate in kbps. Set to null for unconstrained output.";
              };
              maxrateKbps = mkOption {
                type = types.nullOr types.int;
                default = null;
                description = "Maximum bitrate in kbps. Defaults to bitrateKbps when unset.";
              };
              bufsizeKbps = mkOption {
                type = types.nullOr types.int;
                default = null;
                description = "Rate-control buffer in kbps. Defaults to 2x bitrateKbps when unset.";
              };
              useVaapi = mkOption {
                type = types.bool;
                default = false;
                description = "Use VAAPI hardware encoding (h264_vaapi) instead of libx264.";
              };
              vaapiDevice = mkOption {
                type = types.str;
                default = "/dev/dri/renderD128";
                description = "VAAPI render device path used when useVaapi = true.";
              };
              vaapiQp = mkOption {
                type = types.int;
                default = 24;
                description = "VAAPI quality parameter for h264_vaapi.";
              };
              vaapiDriver = mkOption {
                type = types.nullOr types.str;
                default = null;
                description = "Optional LIBVA_DRIVER_NAME value (for example iHD).";
              };
            };
          }
        );
        default = { };
        description = "Named stream definitions. One systemd service is created per stream.";
      };
    };
  };

  config = mkIf cfg.enable {
    systemd.services = mapAttrs' (
      streamName: streamCfg:
      let
        maxrateKbps =
          if streamCfg.maxrateKbps != null then streamCfg.maxrateKbps else streamCfg.bitrateKbps;
        bufsizeKbps =
          if streamCfg.bufsizeKbps != null then
            streamCfg.bufsizeKbps
          else if streamCfg.bitrateKbps != null then
            streamCfg.bitrateKbps * 2
          else
            null;
        x264RateControlArgs =
          if streamCfg.bitrateKbps != null then
            "-b:v ${toString streamCfg.bitrateKbps}k -maxrate ${toString maxrateKbps}k -bufsize ${toString bufsizeKbps}k"
          else
            "";
        vaapiRateControlArgs =
          if streamCfg.bitrateKbps != null then
            "-rc_mode VBR -b:v ${toString streamCfg.bitrateKbps}k -maxrate ${toString maxrateKbps}k -bufsize ${toString bufsizeKbps}k"
          else
            "-rc_mode CQP -qp ${toString streamCfg.vaapiQp}";
        videoCodecArgs =
          if streamCfg.useVaapi then
            "-vaapi_device ${streamCfg.vaapiDevice} -vf format=nv12,hwupload -c:v h264_vaapi -profile:v main -level:v 4.1 ${vaapiRateControlArgs} -g ${
              toString (streamCfg.framerate * 2)
            } -bf 0"
          else
            "-vcodec libx264 -pix_fmt yuv420p -profile:v main -level:v 4.1 -tune zerolatency -preset ${streamCfg.preset} ${x264RateControlArgs} -g ${
              toString (streamCfg.framerate * 2)
            } -bf 0";
      in
      nameValuePair "webcam-rtsp-publisher-${sanitizeName streamName}" {
        description = "Publish webcam stream '${streamName}' to MediaMTX over RTSP";
        wantedBy = [ "multi-user.target" ];
        after = [ "network-online.target" ];
        wants = [ "network-online.target" ];

        serviceConfig = {
          Type = "simple";
          Restart = "always";
          RestartSec = "2";
          Environment = optional (streamCfg.vaapiDriver != null) "LIBVA_DRIVER_NAME=${streamCfg.vaapiDriver}";
          ExecStart = "${pkgs.ffmpeg}/bin/ffmpeg -hide_banner -loglevel warning -f v4l2 -framerate ${toString streamCfg.framerate} -video_size ${streamCfg.videoSize} -i ${streamCfg.device} ${videoCodecArgs} -f rtsp -rtsp_transport tcp ${streamCfg.rtspUrl}";
        };
      }
    ) effectiveStreams;
  };
}
