// Author: fengshengxiong
// Date: 2024/6/23
// Description: 播放歌曲模型

import 'dart:convert';

class PlayerModel {
  ResponseContext? responseContext;
  PlayabilityStatus? playabilityStatus;
  StreamingData? streamingData;
  PlaybackTracking? playbackTracking;
  VideoDetails? videoDetails;
  PlayerConfig? playerConfig;
  Storyboards? storyboards;
  String? trackingParams;
  Attestation? attestation;
  String? adBreakHeartbeatParams;

  PlayerModel({
    this.responseContext,
    this.playabilityStatus,
    this.streamingData,
    this.playbackTracking,
    this.videoDetails,
    this.playerConfig,
    this.storyboards,
    this.trackingParams,
    this.attestation,
    this.adBreakHeartbeatParams,
  });

  factory PlayerModel.fromJson(String str) => PlayerModel.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory PlayerModel.fromMap(Map<String, dynamic> json) => PlayerModel(
    responseContext: json["responseContext"] == null ? null : ResponseContext.fromMap(json["responseContext"]),
    playabilityStatus: json["playabilityStatus"] == null ? null : PlayabilityStatus.fromMap(json["playabilityStatus"]),
    streamingData: json["streamingData"] == null ? null : StreamingData.fromMap(json["streamingData"]),
    playbackTracking: json["playbackTracking"] == null ? null : PlaybackTracking.fromMap(json["playbackTracking"]),
    videoDetails: json["videoDetails"] == null ? null : VideoDetails.fromMap(json["videoDetails"]),
    playerConfig: json["playerConfig"] == null ? null : PlayerConfig.fromMap(json["playerConfig"]),
    storyboards: json["storyboards"] == null ? null : Storyboards.fromMap(json["storyboards"]),
    trackingParams: json["trackingParams"],
    attestation: json["attestation"] == null ? null : Attestation.fromMap(json["attestation"]),
    adBreakHeartbeatParams: json["adBreakHeartbeatParams"],
  );

  Map<String, dynamic> toMap() => {
    "responseContext": responseContext?.toMap(),
    "playabilityStatus": playabilityStatus?.toMap(),
    "streamingData": streamingData?.toMap(),
    "playbackTracking": playbackTracking?.toMap(),
    "videoDetails": videoDetails?.toMap(),
    "playerConfig": playerConfig?.toMap(),
    "storyboards": storyboards?.toMap(),
    "trackingParams": trackingParams,
    "attestation": attestation?.toMap(),
    "adBreakHeartbeatParams": adBreakHeartbeatParams,
  };
}

class Attestation {
  PlayerAttestationRenderer? playerAttestationRenderer;

  Attestation({
    this.playerAttestationRenderer,
  });

  factory Attestation.fromJson(String str) => Attestation.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory Attestation.fromMap(Map<String, dynamic> json) => Attestation(
    playerAttestationRenderer: json["playerAttestationRenderer"] == null ? null : PlayerAttestationRenderer.fromMap(json["playerAttestationRenderer"]),
  );

  Map<String, dynamic> toMap() => {
    "playerAttestationRenderer": playerAttestationRenderer?.toMap(),
  };
}

class PlayerAttestationRenderer {
  String? challenge;

  PlayerAttestationRenderer({
    this.challenge,
  });

  factory PlayerAttestationRenderer.fromJson(String str) => PlayerAttestationRenderer.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory PlayerAttestationRenderer.fromMap(Map<String, dynamic> json) => PlayerAttestationRenderer(
    challenge: json["challenge"],
  );

  Map<String, dynamic> toMap() => {
    "challenge": challenge,
  };
}

class PlayabilityStatus {
  String? status;
  bool? playableInEmbed;
  Backgroundability? backgroundability;
  AudioOnlyPlayability? audioOnlyPlayability;
  Miniplayer? miniplayer;
  String? contextParams;

  PlayabilityStatus({
    this.status,
    this.playableInEmbed,
    this.backgroundability,
    this.audioOnlyPlayability,
    this.miniplayer,
    this.contextParams,
  });

  factory PlayabilityStatus.fromJson(String str) => PlayabilityStatus.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory PlayabilityStatus.fromMap(Map<String, dynamic> json) => PlayabilityStatus(
    status: json["status"],
    playableInEmbed: json["playableInEmbed"],
    backgroundability: json["backgroundability"] == null ? null : Backgroundability.fromMap(json["backgroundability"]),
    audioOnlyPlayability: json["audioOnlyPlayability"] == null ? null : AudioOnlyPlayability.fromMap(json["audioOnlyPlayability"]),
    miniplayer: json["miniplayer"] == null ? null : Miniplayer.fromMap(json["miniplayer"]),
    contextParams: json["contextParams"],
  );

  Map<String, dynamic> toMap() => {
    "status": status,
    "playableInEmbed": playableInEmbed,
    "backgroundability": backgroundability?.toMap(),
    "audioOnlyPlayability": audioOnlyPlayability?.toMap(),
    "miniplayer": miniplayer?.toMap(),
    "contextParams": contextParams,
  };
}

class AudioOnlyPlayability {
  AudioOnlyPlayabilityRenderer? audioOnlyPlayabilityRenderer;

  AudioOnlyPlayability({
    this.audioOnlyPlayabilityRenderer,
  });

  factory AudioOnlyPlayability.fromJson(String str) => AudioOnlyPlayability.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AudioOnlyPlayability.fromMap(Map<String, dynamic> json) => AudioOnlyPlayability(
    audioOnlyPlayabilityRenderer: json["audioOnlyPlayabilityRenderer"] == null ? null : AudioOnlyPlayabilityRenderer.fromMap(json["audioOnlyPlayabilityRenderer"]),
  );

  Map<String, dynamic> toMap() => {
    "audioOnlyPlayabilityRenderer": audioOnlyPlayabilityRenderer?.toMap(),
  };
}

class AudioOnlyPlayabilityRenderer {
  String? trackingParams;
  String? audioOnlyAvailability;

  AudioOnlyPlayabilityRenderer({
    this.trackingParams,
    this.audioOnlyAvailability,
  });

  factory AudioOnlyPlayabilityRenderer.fromJson(String str) => AudioOnlyPlayabilityRenderer.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AudioOnlyPlayabilityRenderer.fromMap(Map<String, dynamic> json) => AudioOnlyPlayabilityRenderer(
    trackingParams: json["trackingParams"],
    audioOnlyAvailability: json["audioOnlyAvailability"],
  );

  Map<String, dynamic> toMap() => {
    "trackingParams": trackingParams,
    "audioOnlyAvailability": audioOnlyAvailability,
  };
}

class Backgroundability {
  BackgroundabilityRenderer? backgroundabilityRenderer;

  Backgroundability({
    this.backgroundabilityRenderer,
  });

  factory Backgroundability.fromJson(String str) => Backgroundability.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory Backgroundability.fromMap(Map<String, dynamic> json) => Backgroundability(
    backgroundabilityRenderer: json["backgroundabilityRenderer"] == null ? null : BackgroundabilityRenderer.fromMap(json["backgroundabilityRenderer"]),
  );

  Map<String, dynamic> toMap() => {
    "backgroundabilityRenderer": backgroundabilityRenderer?.toMap(),
  };
}

class BackgroundabilityRenderer {
  bool? backgroundable;

  BackgroundabilityRenderer({
    this.backgroundable,
  });

  factory BackgroundabilityRenderer.fromJson(String str) => BackgroundabilityRenderer.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory BackgroundabilityRenderer.fromMap(Map<String, dynamic> json) => BackgroundabilityRenderer(
    backgroundable: json["backgroundable"],
  );

  Map<String, dynamic> toMap() => {
    "backgroundable": backgroundable,
  };
}

class Miniplayer {
  MiniplayerRenderer? miniplayerRenderer;

  Miniplayer({
    this.miniplayerRenderer,
  });

  factory Miniplayer.fromJson(String str) => Miniplayer.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory Miniplayer.fromMap(Map<String, dynamic> json) => Miniplayer(
    miniplayerRenderer: json["miniplayerRenderer"] == null ? null : MiniplayerRenderer.fromMap(json["miniplayerRenderer"]),
  );

  Map<String, dynamic> toMap() => {
    "miniplayerRenderer": miniplayerRenderer?.toMap(),
  };
}

class MiniplayerRenderer {
  String? playbackMode;

  MiniplayerRenderer({
    this.playbackMode,
  });

  factory MiniplayerRenderer.fromJson(String str) => MiniplayerRenderer.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory MiniplayerRenderer.fromMap(Map<String, dynamic> json) => MiniplayerRenderer(
    playbackMode: json["playbackMode"],
  );

  Map<String, dynamic> toMap() => {
    "playbackMode": playbackMode,
  };
}

class PlaybackTracking {
  Url? videostatsPlaybackUrl;
  Url? videostatsDelayplayUrl;
  Url? videostatsWatchtimeUrl;
  Url? ptrackingUrl;
  Url? qoeUrl;
  AtrUrl? atrUrl;
  List<int>? videostatsScheduledFlushWalltimeSeconds;
  int? videostatsDefaultFlushIntervalSeconds;

  PlaybackTracking({
    this.videostatsPlaybackUrl,
    this.videostatsDelayplayUrl,
    this.videostatsWatchtimeUrl,
    this.ptrackingUrl,
    this.qoeUrl,
    this.atrUrl,
    this.videostatsScheduledFlushWalltimeSeconds,
    this.videostatsDefaultFlushIntervalSeconds,
  });

  factory PlaybackTracking.fromJson(String str) => PlaybackTracking.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory PlaybackTracking.fromMap(Map<String, dynamic> json) => PlaybackTracking(
    videostatsPlaybackUrl: json["videostatsPlaybackUrl"] == null ? null : Url.fromMap(json["videostatsPlaybackUrl"]),
    videostatsDelayplayUrl: json["videostatsDelayplayUrl"] == null ? null : Url.fromMap(json["videostatsDelayplayUrl"]),
    videostatsWatchtimeUrl: json["videostatsWatchtimeUrl"] == null ? null : Url.fromMap(json["videostatsWatchtimeUrl"]),
    ptrackingUrl: json["ptrackingUrl"] == null ? null : Url.fromMap(json["ptrackingUrl"]),
    qoeUrl: json["qoeUrl"] == null ? null : Url.fromMap(json["qoeUrl"]),
    atrUrl: json["atrUrl"] == null ? null : AtrUrl.fromMap(json["atrUrl"]),
    videostatsScheduledFlushWalltimeSeconds: json["videostatsScheduledFlushWalltimeSeconds"] == null ? [] : List<int>.from(json["videostatsScheduledFlushWalltimeSeconds"]!.map((x) => x)),
    videostatsDefaultFlushIntervalSeconds: json["videostatsDefaultFlushIntervalSeconds"],
  );

  Map<String, dynamic> toMap() => {
    "videostatsPlaybackUrl": videostatsPlaybackUrl?.toMap(),
    "videostatsDelayplayUrl": videostatsDelayplayUrl?.toMap(),
    "videostatsWatchtimeUrl": videostatsWatchtimeUrl?.toMap(),
    "ptrackingUrl": ptrackingUrl?.toMap(),
    "qoeUrl": qoeUrl?.toMap(),
    "atrUrl": atrUrl?.toMap(),
    "videostatsScheduledFlushWalltimeSeconds": videostatsScheduledFlushWalltimeSeconds == null ? [] : List<dynamic>.from(videostatsScheduledFlushWalltimeSeconds!.map((x) => x)),
    "videostatsDefaultFlushIntervalSeconds": videostatsDefaultFlushIntervalSeconds,
  };
}

class AtrUrl {
  String? baseUrl;
  int? elapsedMediaTimeSeconds;
  List<Header>? headers;

  AtrUrl({
    this.baseUrl,
    this.elapsedMediaTimeSeconds,
    this.headers,
  });

  factory AtrUrl.fromJson(String str) => AtrUrl.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AtrUrl.fromMap(Map<String, dynamic> json) => AtrUrl(
    baseUrl: json["baseUrl"],
    elapsedMediaTimeSeconds: json["elapsedMediaTimeSeconds"],
    headers: json["headers"] == null ? [] : List<Header>.from(json["headers"]!.map((x) => Header.fromMap(x))),
  );

  Map<String, dynamic> toMap() => {
    "baseUrl": baseUrl,
    "elapsedMediaTimeSeconds": elapsedMediaTimeSeconds,
    "headers": headers == null ? [] : List<dynamic>.from(headers!.map((x) => x.toMap())),
  };
}

class Header {
  String? headerType;

  Header({
    this.headerType,
  });

  factory Header.fromJson(String str) => Header.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory Header.fromMap(Map<String, dynamic> json) => Header(
    headerType: json["headerType"],
  );

  Map<String, dynamic> toMap() => {
    "headerType": headerType,
  };
}

class Url {
  String? baseUrl;
  List<Header>? headers;

  Url({
    this.baseUrl,
    this.headers,
  });

  factory Url.fromJson(String str) => Url.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory Url.fromMap(Map<String, dynamic> json) => Url(
    baseUrl: json["baseUrl"],
    headers: json["headers"] == null ? [] : List<Header>.from(json["headers"]!.map((x) => Header.fromMap(x))),
  );

  Map<String, dynamic> toMap() => {
    "baseUrl": baseUrl,
    "headers": headers == null ? [] : List<dynamic>.from(headers!.map((x) => x.toMap())),
  };
}

class PlayerConfig {
  AudioConfig? audioConfig;
  ExoPlayerConfig? exoPlayerConfig;
  AdRequestConfig? adRequestConfig;
  NetworkProtocolConfig? networkProtocolConfig;
  AndroidNetworkStackConfig? androidNetworkStackConfig;
  LidarSdkConfig? lidarSdkConfig;
  AndroidMedialibConfig? androidMedialibConfig;
  VariableSpeedConfig? variableSpeedConfig;
  DecodeQualityConfig? decodeQualityConfig;
  PlayerRestorationConfig? playerRestorationConfig;
  AndroidPlayerStatsConfig? androidPlayerStatsConfig;
  RetryConfig? retryConfig;
  CmsPathProbeConfig? cmsPathProbeConfig;
  MediaCommonConfig? mediaCommonConfig;
  TaskCoordinatorConfig? taskCoordinatorConfig;

  PlayerConfig({
    this.audioConfig,
    this.exoPlayerConfig,
    this.adRequestConfig,
    this.networkProtocolConfig,
    this.androidNetworkStackConfig,
    this.lidarSdkConfig,
    this.androidMedialibConfig,
    this.variableSpeedConfig,
    this.decodeQualityConfig,
    this.playerRestorationConfig,
    this.androidPlayerStatsConfig,
    this.retryConfig,
    this.cmsPathProbeConfig,
    this.mediaCommonConfig,
    this.taskCoordinatorConfig,
  });

  factory PlayerConfig.fromJson(String str) => PlayerConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory PlayerConfig.fromMap(Map<String, dynamic> json) => PlayerConfig(
    audioConfig: json["audioConfig"] == null ? null : AudioConfig.fromMap(json["audioConfig"]),
    exoPlayerConfig: json["exoPlayerConfig"] == null ? null : ExoPlayerConfig.fromMap(json["exoPlayerConfig"]),
    adRequestConfig: json["adRequestConfig"] == null ? null : AdRequestConfig.fromMap(json["adRequestConfig"]),
    networkProtocolConfig: json["networkProtocolConfig"] == null ? null : NetworkProtocolConfig.fromMap(json["networkProtocolConfig"]),
    androidNetworkStackConfig: json["androidNetworkStackConfig"] == null ? null : AndroidNetworkStackConfig.fromMap(json["androidNetworkStackConfig"]),
    lidarSdkConfig: json["lidarSdkConfig"] == null ? null : LidarSdkConfig.fromMap(json["lidarSdkConfig"]),
    androidMedialibConfig: json["androidMedialibConfig"] == null ? null : AndroidMedialibConfig.fromMap(json["androidMedialibConfig"]),
    variableSpeedConfig: json["variableSpeedConfig"] == null ? null : VariableSpeedConfig.fromMap(json["variableSpeedConfig"]),
    decodeQualityConfig: json["decodeQualityConfig"] == null ? null : DecodeQualityConfig.fromMap(json["decodeQualityConfig"]),
    playerRestorationConfig: json["playerRestorationConfig"] == null ? null : PlayerRestorationConfig.fromMap(json["playerRestorationConfig"]),
    androidPlayerStatsConfig: json["androidPlayerStatsConfig"] == null ? null : AndroidPlayerStatsConfig.fromMap(json["androidPlayerStatsConfig"]),
    retryConfig: json["retryConfig"] == null ? null : RetryConfig.fromMap(json["retryConfig"]),
    cmsPathProbeConfig: json["cmsPathProbeConfig"] == null ? null : CmsPathProbeConfig.fromMap(json["cmsPathProbeConfig"]),
    mediaCommonConfig: json["mediaCommonConfig"] == null ? null : MediaCommonConfig.fromMap(json["mediaCommonConfig"]),
    taskCoordinatorConfig: json["taskCoordinatorConfig"] == null ? null : TaskCoordinatorConfig.fromMap(json["taskCoordinatorConfig"]),
  );

  Map<String, dynamic> toMap() => {
    "audioConfig": audioConfig?.toMap(),
    "exoPlayerConfig": exoPlayerConfig?.toMap(),
    "adRequestConfig": adRequestConfig?.toMap(),
    "networkProtocolConfig": networkProtocolConfig?.toMap(),
    "androidNetworkStackConfig": androidNetworkStackConfig?.toMap(),
    "lidarSdkConfig": lidarSdkConfig?.toMap(),
    "androidMedialibConfig": androidMedialibConfig?.toMap(),
    "variableSpeedConfig": variableSpeedConfig?.toMap(),
    "decodeQualityConfig": decodeQualityConfig?.toMap(),
    "playerRestorationConfig": playerRestorationConfig?.toMap(),
    "androidPlayerStatsConfig": androidPlayerStatsConfig?.toMap(),
    "retryConfig": retryConfig?.toMap(),
    "cmsPathProbeConfig": cmsPathProbeConfig?.toMap(),
    "mediaCommonConfig": mediaCommonConfig?.toMap(),
    "taskCoordinatorConfig": taskCoordinatorConfig?.toMap(),
  };
}

class AdRequestConfig {
  bool? useCriticalExecOnAdsPrep;
  bool? userCriticalExecOnAdsProcessing;

  AdRequestConfig({
    this.useCriticalExecOnAdsPrep,
    this.userCriticalExecOnAdsProcessing,
  });

  factory AdRequestConfig.fromJson(String str) => AdRequestConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AdRequestConfig.fromMap(Map<String, dynamic> json) => AdRequestConfig(
    useCriticalExecOnAdsPrep: json["useCriticalExecOnAdsPrep"],
    userCriticalExecOnAdsProcessing: json["userCriticalExecOnAdsProcessing"],
  );

  Map<String, dynamic> toMap() => {
    "useCriticalExecOnAdsPrep": useCriticalExecOnAdsPrep,
    "userCriticalExecOnAdsProcessing": userCriticalExecOnAdsProcessing,
  };
}

class AndroidMedialibConfig {
  bool? isItag18MainProfile;
  double? viewportSizeFraction;

  AndroidMedialibConfig({
    this.isItag18MainProfile,
    this.viewportSizeFraction,
  });

  factory AndroidMedialibConfig.fromJson(String str) => AndroidMedialibConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AndroidMedialibConfig.fromMap(Map<String, dynamic> json) => AndroidMedialibConfig(
    isItag18MainProfile: json["isItag18MainProfile"],
    viewportSizeFraction: json["viewportSizeFraction"]?.toDouble(),
  );

  Map<String, dynamic> toMap() => {
    "isItag18MainProfile": isItag18MainProfile,
    "viewportSizeFraction": viewportSizeFraction,
  };
}

class AndroidNetworkStackConfig {
  String? networkStack;
  AndroidMetadataNetworkConfig? androidMetadataNetworkConfig;

  AndroidNetworkStackConfig({
    this.networkStack,
    this.androidMetadataNetworkConfig,
  });

  factory AndroidNetworkStackConfig.fromJson(String str) => AndroidNetworkStackConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AndroidNetworkStackConfig.fromMap(Map<String, dynamic> json) => AndroidNetworkStackConfig(
    networkStack: json["networkStack"],
    androidMetadataNetworkConfig: json["androidMetadataNetworkConfig"] == null ? null : AndroidMetadataNetworkConfig.fromMap(json["androidMetadataNetworkConfig"]),
  );

  Map<String, dynamic> toMap() => {
    "networkStack": networkStack,
    "androidMetadataNetworkConfig": androidMetadataNetworkConfig?.toMap(),
  };
}

class AndroidMetadataNetworkConfig {
  bool? coalesceRequests;

  AndroidMetadataNetworkConfig({
    this.coalesceRequests,
  });

  factory AndroidMetadataNetworkConfig.fromJson(String str) => AndroidMetadataNetworkConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AndroidMetadataNetworkConfig.fromMap(Map<String, dynamic> json) => AndroidMetadataNetworkConfig(
    coalesceRequests: json["coalesceRequests"],
  );

  Map<String, dynamic> toMap() => {
    "coalesceRequests": coalesceRequests,
  };
}

class AndroidPlayerStatsConfig {
  bool? usePblForAttestationReporting;
  bool? usePblForHeartbeatReporting;
  bool? usePblForPlaybacktrackingReporting;
  bool? usePblForQoeReporting;
  bool? changeCpnOnFatalPlaybackError;

  AndroidPlayerStatsConfig({
    this.usePblForAttestationReporting,
    this.usePblForHeartbeatReporting,
    this.usePblForPlaybacktrackingReporting,
    this.usePblForQoeReporting,
    this.changeCpnOnFatalPlaybackError,
  });

  factory AndroidPlayerStatsConfig.fromJson(String str) => AndroidPlayerStatsConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AndroidPlayerStatsConfig.fromMap(Map<String, dynamic> json) => AndroidPlayerStatsConfig(
    usePblForAttestationReporting: json["usePblForAttestationReporting"],
    usePblForHeartbeatReporting: json["usePblForHeartbeatReporting"],
    usePblForPlaybacktrackingReporting: json["usePblForPlaybacktrackingReporting"],
    usePblForQoeReporting: json["usePblForQoeReporting"],
    changeCpnOnFatalPlaybackError: json["changeCpnOnFatalPlaybackError"],
  );

  Map<String, dynamic> toMap() => {
    "usePblForAttestationReporting": usePblForAttestationReporting,
    "usePblForHeartbeatReporting": usePblForHeartbeatReporting,
    "usePblForPlaybacktrackingReporting": usePblForPlaybacktrackingReporting,
    "usePblForQoeReporting": usePblForQoeReporting,
    "changeCpnOnFatalPlaybackError": changeCpnOnFatalPlaybackError,
  };
}

class AudioConfig {
  double? loudnessDb;
  double? perceptualLoudnessDb;
  bool? playAudioOnly;
  bool? enablePerFormatLoudness;

  AudioConfig({
    this.loudnessDb,
    this.perceptualLoudnessDb,
    this.playAudioOnly,
    this.enablePerFormatLoudness,
  });

  factory AudioConfig.fromJson(String str) => AudioConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AudioConfig.fromMap(Map<String, dynamic> json) => AudioConfig(
    loudnessDb: json["loudnessDb"]?.toDouble(),
    perceptualLoudnessDb: json["perceptualLoudnessDb"]?.toDouble(),
    playAudioOnly: json["playAudioOnly"],
    enablePerFormatLoudness: json["enablePerFormatLoudness"],
  );

  Map<String, dynamic> toMap() => {
    "loudnessDb": loudnessDb,
    "perceptualLoudnessDb": perceptualLoudnessDb,
    "playAudioOnly": playAudioOnly,
    "enablePerFormatLoudness": enablePerFormatLoudness,
  };
}

class CmsPathProbeConfig {
  int? cmsPathProbeDelayMs;

  CmsPathProbeConfig({
    this.cmsPathProbeDelayMs,
  });

  factory CmsPathProbeConfig.fromJson(String str) => CmsPathProbeConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory CmsPathProbeConfig.fromMap(Map<String, dynamic> json) => CmsPathProbeConfig(
    cmsPathProbeDelayMs: json["cmsPathProbeDelayMs"],
  );

  Map<String, dynamic> toMap() => {
    "cmsPathProbeDelayMs": cmsPathProbeDelayMs,
  };
}

class DecodeQualityConfig {
  int? maximumVideoDecodeVerticalResolution;

  DecodeQualityConfig({
    this.maximumVideoDecodeVerticalResolution,
  });

  factory DecodeQualityConfig.fromJson(String str) => DecodeQualityConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory DecodeQualityConfig.fromMap(Map<String, dynamic> json) => DecodeQualityConfig(
    maximumVideoDecodeVerticalResolution: json["maximumVideoDecodeVerticalResolution"],
  );

  Map<String, dynamic> toMap() => {
    "maximumVideoDecodeVerticalResolution": maximumVideoDecodeVerticalResolution,
  };
}

class ExoPlayerConfig {
  bool? useExoPlayer;
  bool? useAdaptiveBitrate;
  int? maxInitialByteRate;
  int? minDurationForQualityIncreaseMs;
  int? maxDurationForQualityDecreaseMs;
  int? minDurationToRetainAfterDiscardMs;
  int? lowWatermarkMs;
  int? highWatermarkMs;
  double? lowPoolLoad;
  double? highPoolLoad;
  double? sufficientBandwidthOverhead;
  int? bufferChunkSizeKb;
  int? httpConnectTimeoutMs;
  int? httpReadTimeoutMs;
  int? numAudioSegmentsPerFetch;
  int? numVideoSegmentsPerFetch;
  int? minDurationForPlaybackStartMs;
  bool? enableExoplayerReuse;
  bool? useRadioTypeForInitialQualitySelection;
  bool? blacklistFormatOnError;
  bool? enableBandaidHttpDataSource;
  int? httpLoadTimeoutMs;
  bool? canPlayHdDrm;
  int? videoBufferSegmentCount;
  int? audioBufferSegmentCount;
  bool? useAbruptSplicing;
  int? minRetryCount;
  int? minChunksNeededToPreferOffline;
  int? secondsToMaxAggressiveness;
  bool? enableSurfaceviewResizeWorkaround;
  bool? enableVp9IfThresholdsPass;
  bool? matchQualityToViewportOnUnfullscreen;
  List<String>? lowAudioQualityConnTypes;
  bool? useDashForLiveStreams;
  bool? enableLibvpxVideoTrackRenderer;
  int? lowAudioQualityBandwidthThresholdBps;
  bool? enableVariableSpeedPlayback;
  bool? preferOnesieBufferedFormat;
  int? minimumBandwidthSampleBytes;
  bool? useDashForOtfAndCompletedLiveStreams;
  bool? disableCacheAwareVideoFormatEvaluation;
  bool? useLiveDvrForDashLiveStreams;
  bool? cronetResetTimeoutOnRedirects;
  bool? emitVideoDecoderChangeEvents;
  String? onesieVideoBufferLoadTimeoutMs;
  String? onesieVideoBufferReadTimeoutMs;
  bool? libvpxEnableGl;
  bool? enableVp9EncryptedIfThresholdsPass;
  bool? enableOpus;
  bool? usePredictedBuffer;
  int? maxReadAheadMediaTimeMs;
  bool? useMediaTimeCappedLoadControl;
  int? allowCacheOverrideToLowerQualitiesWithinRange;
  bool? allowDroppingUndecodedFrames;
  int? minDurationForPlaybackRestartMs;
  String? serverProvidedBandwidthHeader;
  String? liveOnlyPegStrategy;
  bool? enableRedirectorHostFallback;
  bool? enableHighlyAvailableFormatFallbackOnPcr;
  bool? recordTrackRendererTimingEvents;
  int? minErrorsForRedirectorHostFallback;
  List<String>? nonHardwareMediaCodecNames;
  bool? enableVp9IfInHardware;
  bool? enableVp9EncryptedIfInHardware;
  bool? useOpusMedAsLowQualityAudio;
  int? minErrorsForPcrFallback;
  bool? useStickyRedirectHttpDataSource;
  bool? onlyVideoBandwidth;
  bool? useRedirectorOnNetworkChange;
  bool? enableMaxReadaheadAbrThreshold;
  bool? cacheCheckDirectoryWritabilityOnce;
  String? predictorType;
  double? slidingPercentile;
  int? slidingWindowSize;
  int? maxFrameDropIntervalMs;
  bool? ignoreLoadTimeoutForFallback;
  int? serverBweMultiplier;
  int? drmMaxKeyfetchDelayMs;
  int? maxResolutionForWhiteNoise;
  String? whiteNoiseRenderEffectMode;
  bool? enableLibvpxHdr;
  bool? enableCacheAwareStreamSelection;
  bool? useExoCronetDataSource;
  int? whiteNoiseScale;
  int? whiteNoiseOffset;
  bool? preventVideoFrameLaggingWithLibvpx;
  bool? enableMediaCodecHdr;
  bool? enableMediaCodecSwHdr;
  int? liveOnlyWindowChunks;
  List<int>? bearerMinDurationToRetainAfterDiscardMs;
  bool? forceWidevineL3;
  bool? useAverageBitrate;
  bool? useMedialibAudioTrackRendererForLive;
  bool? useExoPlayerV2;
  bool? logMediaRequestEventsToCsi;
  bool? onesieFixNonZeroStartTimeFormatSelection;
  int? liveOnlyReadaheadStepSizeChunks;
  int? liveOnlyBufferHealthHalfLifeSeconds;
  double? liveOnlyMinBufferHealthRatio;
  int? liveOnlyMinLatencyToSeekRatio;
  String? manifestlessPartialChunkStrategy;
  bool? ignoreViewportSizeWhenSticky;
  bool? enableLibvpxFallback;
  bool? disableLibvpxLoopFilter;
  bool? enableVpxMediaView;
  int? hdrMinScreenBrightness;
  int? hdrMaxScreenBrightnessThreshold;
  bool? onesieDataSourceAboveCacheDataSource;
  int? httpNonplayerLoadTimeoutMs;
  String? numVideoSegmentsPerFetchStrategy;
  int? maxVideoDurationPerFetchMs;
  int? maxVideoEstimatedLoadDurationMs;
  int? estimatedServerClockHalfLife;
  bool? estimatedServerClockStrictOffset;
  int? minReadAheadMediaTimeMs;
  int? readAheadGrowthRate;
  bool? useDynamicReadAhead;
  bool? useYtVodMediaSourceForV2;
  bool? enableV2Gapless;
  bool? useLiveHeadTimeMillis;
  bool? allowTrackSelectionWithUpdatedVideoItagsForExoV2;
  int? maxAllowableTimeBeforeMediaTimeUpdateSec;
  bool? enableDynamicHdr;
  bool? v2PerformEarlyStreamSelection;
  bool? v2UsePlaybackStreamSelectionResult;
  int? v2MinTimeBetweenAbrReevaluationMs;
  bool? avoidReusePlaybackAcrossLoadvideos;
  bool? enableInfiniteNetworkLoadingRetries;
  bool? reportExoPlayerStateOnTransition;
  String? manifestlessSequenceMethod;
  bool? useLiveHeadWindow;
  bool? enableDynamicHdrInHardware;
  int? ultralowAudioQualityBandwidthThresholdBps;
  bool? retryLiveNetNocontentWithDelay;
  bool? ignoreUnneededSeeksToLiveHead;
  double? drmMetricsQoeLoggingFraction;
  int? liveNetNocontentMaximumErrors;
  int? slidingPercentileScalar;
  int? minAdaptiveVideoQuality;
  int? platypusBackBufferDurationMs;

  ExoPlayerConfig({
    this.useExoPlayer,
    this.useAdaptiveBitrate,
    this.maxInitialByteRate,
    this.minDurationForQualityIncreaseMs,
    this.maxDurationForQualityDecreaseMs,
    this.minDurationToRetainAfterDiscardMs,
    this.lowWatermarkMs,
    this.highWatermarkMs,
    this.lowPoolLoad,
    this.highPoolLoad,
    this.sufficientBandwidthOverhead,
    this.bufferChunkSizeKb,
    this.httpConnectTimeoutMs,
    this.httpReadTimeoutMs,
    this.numAudioSegmentsPerFetch,
    this.numVideoSegmentsPerFetch,
    this.minDurationForPlaybackStartMs,
    this.enableExoplayerReuse,
    this.useRadioTypeForInitialQualitySelection,
    this.blacklistFormatOnError,
    this.enableBandaidHttpDataSource,
    this.httpLoadTimeoutMs,
    this.canPlayHdDrm,
    this.videoBufferSegmentCount,
    this.audioBufferSegmentCount,
    this.useAbruptSplicing,
    this.minRetryCount,
    this.minChunksNeededToPreferOffline,
    this.secondsToMaxAggressiveness,
    this.enableSurfaceviewResizeWorkaround,
    this.enableVp9IfThresholdsPass,
    this.matchQualityToViewportOnUnfullscreen,
    this.lowAudioQualityConnTypes,
    this.useDashForLiveStreams,
    this.enableLibvpxVideoTrackRenderer,
    this.lowAudioQualityBandwidthThresholdBps,
    this.enableVariableSpeedPlayback,
    this.preferOnesieBufferedFormat,
    this.minimumBandwidthSampleBytes,
    this.useDashForOtfAndCompletedLiveStreams,
    this.disableCacheAwareVideoFormatEvaluation,
    this.useLiveDvrForDashLiveStreams,
    this.cronetResetTimeoutOnRedirects,
    this.emitVideoDecoderChangeEvents,
    this.onesieVideoBufferLoadTimeoutMs,
    this.onesieVideoBufferReadTimeoutMs,
    this.libvpxEnableGl,
    this.enableVp9EncryptedIfThresholdsPass,
    this.enableOpus,
    this.usePredictedBuffer,
    this.maxReadAheadMediaTimeMs,
    this.useMediaTimeCappedLoadControl,
    this.allowCacheOverrideToLowerQualitiesWithinRange,
    this.allowDroppingUndecodedFrames,
    this.minDurationForPlaybackRestartMs,
    this.serverProvidedBandwidthHeader,
    this.liveOnlyPegStrategy,
    this.enableRedirectorHostFallback,
    this.enableHighlyAvailableFormatFallbackOnPcr,
    this.recordTrackRendererTimingEvents,
    this.minErrorsForRedirectorHostFallback,
    this.nonHardwareMediaCodecNames,
    this.enableVp9IfInHardware,
    this.enableVp9EncryptedIfInHardware,
    this.useOpusMedAsLowQualityAudio,
    this.minErrorsForPcrFallback,
    this.useStickyRedirectHttpDataSource,
    this.onlyVideoBandwidth,
    this.useRedirectorOnNetworkChange,
    this.enableMaxReadaheadAbrThreshold,
    this.cacheCheckDirectoryWritabilityOnce,
    this.predictorType,
    this.slidingPercentile,
    this.slidingWindowSize,
    this.maxFrameDropIntervalMs,
    this.ignoreLoadTimeoutForFallback,
    this.serverBweMultiplier,
    this.drmMaxKeyfetchDelayMs,
    this.maxResolutionForWhiteNoise,
    this.whiteNoiseRenderEffectMode,
    this.enableLibvpxHdr,
    this.enableCacheAwareStreamSelection,
    this.useExoCronetDataSource,
    this.whiteNoiseScale,
    this.whiteNoiseOffset,
    this.preventVideoFrameLaggingWithLibvpx,
    this.enableMediaCodecHdr,
    this.enableMediaCodecSwHdr,
    this.liveOnlyWindowChunks,
    this.bearerMinDurationToRetainAfterDiscardMs,
    this.forceWidevineL3,
    this.useAverageBitrate,
    this.useMedialibAudioTrackRendererForLive,
    this.useExoPlayerV2,
    this.logMediaRequestEventsToCsi,
    this.onesieFixNonZeroStartTimeFormatSelection,
    this.liveOnlyReadaheadStepSizeChunks,
    this.liveOnlyBufferHealthHalfLifeSeconds,
    this.liveOnlyMinBufferHealthRatio,
    this.liveOnlyMinLatencyToSeekRatio,
    this.manifestlessPartialChunkStrategy,
    this.ignoreViewportSizeWhenSticky,
    this.enableLibvpxFallback,
    this.disableLibvpxLoopFilter,
    this.enableVpxMediaView,
    this.hdrMinScreenBrightness,
    this.hdrMaxScreenBrightnessThreshold,
    this.onesieDataSourceAboveCacheDataSource,
    this.httpNonplayerLoadTimeoutMs,
    this.numVideoSegmentsPerFetchStrategy,
    this.maxVideoDurationPerFetchMs,
    this.maxVideoEstimatedLoadDurationMs,
    this.estimatedServerClockHalfLife,
    this.estimatedServerClockStrictOffset,
    this.minReadAheadMediaTimeMs,
    this.readAheadGrowthRate,
    this.useDynamicReadAhead,
    this.useYtVodMediaSourceForV2,
    this.enableV2Gapless,
    this.useLiveHeadTimeMillis,
    this.allowTrackSelectionWithUpdatedVideoItagsForExoV2,
    this.maxAllowableTimeBeforeMediaTimeUpdateSec,
    this.enableDynamicHdr,
    this.v2PerformEarlyStreamSelection,
    this.v2UsePlaybackStreamSelectionResult,
    this.v2MinTimeBetweenAbrReevaluationMs,
    this.avoidReusePlaybackAcrossLoadvideos,
    this.enableInfiniteNetworkLoadingRetries,
    this.reportExoPlayerStateOnTransition,
    this.manifestlessSequenceMethod,
    this.useLiveHeadWindow,
    this.enableDynamicHdrInHardware,
    this.ultralowAudioQualityBandwidthThresholdBps,
    this.retryLiveNetNocontentWithDelay,
    this.ignoreUnneededSeeksToLiveHead,
    this.drmMetricsQoeLoggingFraction,
    this.liveNetNocontentMaximumErrors,
    this.slidingPercentileScalar,
    this.minAdaptiveVideoQuality,
    this.platypusBackBufferDurationMs,
  });

  factory ExoPlayerConfig.fromJson(String str) => ExoPlayerConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory ExoPlayerConfig.fromMap(Map<String, dynamic> json) => ExoPlayerConfig(
    useExoPlayer: json["useExoPlayer"],
    useAdaptiveBitrate: json["useAdaptiveBitrate"],
    maxInitialByteRate: json["maxInitialByteRate"],
    minDurationForQualityIncreaseMs: json["minDurationForQualityIncreaseMs"],
    maxDurationForQualityDecreaseMs: json["maxDurationForQualityDecreaseMs"],
    minDurationToRetainAfterDiscardMs: json["minDurationToRetainAfterDiscardMs"],
    lowWatermarkMs: json["lowWatermarkMs"],
    highWatermarkMs: json["highWatermarkMs"],
    lowPoolLoad: json["lowPoolLoad"]?.toDouble(),
    highPoolLoad: json["highPoolLoad"]?.toDouble(),
    sufficientBandwidthOverhead: json["sufficientBandwidthOverhead"]?.toDouble(),
    bufferChunkSizeKb: json["bufferChunkSizeKb"],
    httpConnectTimeoutMs: json["httpConnectTimeoutMs"],
    httpReadTimeoutMs: json["httpReadTimeoutMs"],
    numAudioSegmentsPerFetch: json["numAudioSegmentsPerFetch"],
    numVideoSegmentsPerFetch: json["numVideoSegmentsPerFetch"],
    minDurationForPlaybackStartMs: json["minDurationForPlaybackStartMs"],
    enableExoplayerReuse: json["enableExoplayerReuse"],
    useRadioTypeForInitialQualitySelection: json["useRadioTypeForInitialQualitySelection"],
    blacklistFormatOnError: json["blacklistFormatOnError"],
    enableBandaidHttpDataSource: json["enableBandaidHttpDataSource"],
    httpLoadTimeoutMs: json["httpLoadTimeoutMs"],
    canPlayHdDrm: json["canPlayHdDrm"],
    videoBufferSegmentCount: json["videoBufferSegmentCount"],
    audioBufferSegmentCount: json["audioBufferSegmentCount"],
    useAbruptSplicing: json["useAbruptSplicing"],
    minRetryCount: json["minRetryCount"],
    minChunksNeededToPreferOffline: json["minChunksNeededToPreferOffline"],
    secondsToMaxAggressiveness: json["secondsToMaxAggressiveness"],
    enableSurfaceviewResizeWorkaround: json["enableSurfaceviewResizeWorkaround"],
    enableVp9IfThresholdsPass: json["enableVp9IfThresholdsPass"],
    matchQualityToViewportOnUnfullscreen: json["matchQualityToViewportOnUnfullscreen"],
    lowAudioQualityConnTypes: json["lowAudioQualityConnTypes"] == null ? [] : List<String>.from(json["lowAudioQualityConnTypes"]!.map((x) => x)),
    useDashForLiveStreams: json["useDashForLiveStreams"],
    enableLibvpxVideoTrackRenderer: json["enableLibvpxVideoTrackRenderer"],
    lowAudioQualityBandwidthThresholdBps: json["lowAudioQualityBandwidthThresholdBps"],
    enableVariableSpeedPlayback: json["enableVariableSpeedPlayback"],
    preferOnesieBufferedFormat: json["preferOnesieBufferedFormat"],
    minimumBandwidthSampleBytes: json["minimumBandwidthSampleBytes"],
    useDashForOtfAndCompletedLiveStreams: json["useDashForOtfAndCompletedLiveStreams"],
    disableCacheAwareVideoFormatEvaluation: json["disableCacheAwareVideoFormatEvaluation"],
    useLiveDvrForDashLiveStreams: json["useLiveDvrForDashLiveStreams"],
    cronetResetTimeoutOnRedirects: json["cronetResetTimeoutOnRedirects"],
    emitVideoDecoderChangeEvents: json["emitVideoDecoderChangeEvents"],
    onesieVideoBufferLoadTimeoutMs: json["onesieVideoBufferLoadTimeoutMs"],
    onesieVideoBufferReadTimeoutMs: json["onesieVideoBufferReadTimeoutMs"],
    libvpxEnableGl: json["libvpxEnableGl"],
    enableVp9EncryptedIfThresholdsPass: json["enableVp9EncryptedIfThresholdsPass"],
    enableOpus: json["enableOpus"],
    usePredictedBuffer: json["usePredictedBuffer"],
    maxReadAheadMediaTimeMs: json["maxReadAheadMediaTimeMs"],
    useMediaTimeCappedLoadControl: json["useMediaTimeCappedLoadControl"],
    allowCacheOverrideToLowerQualitiesWithinRange: json["allowCacheOverrideToLowerQualitiesWithinRange"],
    allowDroppingUndecodedFrames: json["allowDroppingUndecodedFrames"],
    minDurationForPlaybackRestartMs: json["minDurationForPlaybackRestartMs"],
    serverProvidedBandwidthHeader: json["serverProvidedBandwidthHeader"],
    liveOnlyPegStrategy: json["liveOnlyPegStrategy"],
    enableRedirectorHostFallback: json["enableRedirectorHostFallback"],
    enableHighlyAvailableFormatFallbackOnPcr: json["enableHighlyAvailableFormatFallbackOnPcr"],
    recordTrackRendererTimingEvents: json["recordTrackRendererTimingEvents"],
    minErrorsForRedirectorHostFallback: json["minErrorsForRedirectorHostFallback"],
    nonHardwareMediaCodecNames: json["nonHardwareMediaCodecNames"] == null ? [] : List<String>.from(json["nonHardwareMediaCodecNames"]!.map((x) => x)),
    enableVp9IfInHardware: json["enableVp9IfInHardware"],
    enableVp9EncryptedIfInHardware: json["enableVp9EncryptedIfInHardware"],
    useOpusMedAsLowQualityAudio: json["useOpusMedAsLowQualityAudio"],
    minErrorsForPcrFallback: json["minErrorsForPcrFallback"],
    useStickyRedirectHttpDataSource: json["useStickyRedirectHttpDataSource"],
    onlyVideoBandwidth: json["onlyVideoBandwidth"],
    useRedirectorOnNetworkChange: json["useRedirectorOnNetworkChange"],
    enableMaxReadaheadAbrThreshold: json["enableMaxReadaheadAbrThreshold"],
    cacheCheckDirectoryWritabilityOnce: json["cacheCheckDirectoryWritabilityOnce"],
    predictorType: json["predictorType"],
    slidingPercentile: json["slidingPercentile"]?.toDouble(),
    slidingWindowSize: json["slidingWindowSize"],
    maxFrameDropIntervalMs: json["maxFrameDropIntervalMs"],
    ignoreLoadTimeoutForFallback: json["ignoreLoadTimeoutForFallback"],
    serverBweMultiplier: json["serverBweMultiplier"],
    drmMaxKeyfetchDelayMs: json["drmMaxKeyfetchDelayMs"],
    maxResolutionForWhiteNoise: json["maxResolutionForWhiteNoise"],
    whiteNoiseRenderEffectMode: json["whiteNoiseRenderEffectMode"],
    enableLibvpxHdr: json["enableLibvpxHdr"],
    enableCacheAwareStreamSelection: json["enableCacheAwareStreamSelection"],
    useExoCronetDataSource: json["useExoCronetDataSource"],
    whiteNoiseScale: json["whiteNoiseScale"],
    whiteNoiseOffset: json["whiteNoiseOffset"],
    preventVideoFrameLaggingWithLibvpx: json["preventVideoFrameLaggingWithLibvpx"],
    enableMediaCodecHdr: json["enableMediaCodecHdr"],
    enableMediaCodecSwHdr: json["enableMediaCodecSwHdr"],
    liveOnlyWindowChunks: json["liveOnlyWindowChunks"],
    bearerMinDurationToRetainAfterDiscardMs: json["bearerMinDurationToRetainAfterDiscardMs"] == null ? [] : List<int>.from(json["bearerMinDurationToRetainAfterDiscardMs"]!.map((x) => x)),
    forceWidevineL3: json["forceWidevineL3"],
    useAverageBitrate: json["useAverageBitrate"],
    useMedialibAudioTrackRendererForLive: json["useMedialibAudioTrackRendererForLive"],
    useExoPlayerV2: json["useExoPlayerV2"],
    logMediaRequestEventsToCsi: json["logMediaRequestEventsToCsi"],
    onesieFixNonZeroStartTimeFormatSelection: json["onesieFixNonZeroStartTimeFormatSelection"],
    liveOnlyReadaheadStepSizeChunks: json["liveOnlyReadaheadStepSizeChunks"],
    liveOnlyBufferHealthHalfLifeSeconds: json["liveOnlyBufferHealthHalfLifeSeconds"],
    liveOnlyMinBufferHealthRatio: json["liveOnlyMinBufferHealthRatio"]?.toDouble(),
    liveOnlyMinLatencyToSeekRatio: json["liveOnlyMinLatencyToSeekRatio"],
    manifestlessPartialChunkStrategy: json["manifestlessPartialChunkStrategy"],
    ignoreViewportSizeWhenSticky: json["ignoreViewportSizeWhenSticky"],
    enableLibvpxFallback: json["enableLibvpxFallback"],
    disableLibvpxLoopFilter: json["disableLibvpxLoopFilter"],
    enableVpxMediaView: json["enableVpxMediaView"],
    hdrMinScreenBrightness: json["hdrMinScreenBrightness"],
    hdrMaxScreenBrightnessThreshold: json["hdrMaxScreenBrightnessThreshold"],
    onesieDataSourceAboveCacheDataSource: json["onesieDataSourceAboveCacheDataSource"],
    httpNonplayerLoadTimeoutMs: json["httpNonplayerLoadTimeoutMs"],
    numVideoSegmentsPerFetchStrategy: json["numVideoSegmentsPerFetchStrategy"],
    maxVideoDurationPerFetchMs: json["maxVideoDurationPerFetchMs"],
    maxVideoEstimatedLoadDurationMs: json["maxVideoEstimatedLoadDurationMs"],
    estimatedServerClockHalfLife: json["estimatedServerClockHalfLife"],
    estimatedServerClockStrictOffset: json["estimatedServerClockStrictOffset"],
    minReadAheadMediaTimeMs: json["minReadAheadMediaTimeMs"],
    readAheadGrowthRate: json["readAheadGrowthRate"],
    useDynamicReadAhead: json["useDynamicReadAhead"],
    useYtVodMediaSourceForV2: json["useYtVodMediaSourceForV2"],
    enableV2Gapless: json["enableV2Gapless"],
    useLiveHeadTimeMillis: json["useLiveHeadTimeMillis"],
    allowTrackSelectionWithUpdatedVideoItagsForExoV2: json["allowTrackSelectionWithUpdatedVideoItagsForExoV2"],
    maxAllowableTimeBeforeMediaTimeUpdateSec: json["maxAllowableTimeBeforeMediaTimeUpdateSec"],
    enableDynamicHdr: json["enableDynamicHdr"],
    v2PerformEarlyStreamSelection: json["v2PerformEarlyStreamSelection"],
    v2UsePlaybackStreamSelectionResult: json["v2UsePlaybackStreamSelectionResult"],
    v2MinTimeBetweenAbrReevaluationMs: json["v2MinTimeBetweenAbrReevaluationMs"],
    avoidReusePlaybackAcrossLoadvideos: json["avoidReusePlaybackAcrossLoadvideos"],
    enableInfiniteNetworkLoadingRetries: json["enableInfiniteNetworkLoadingRetries"],
    reportExoPlayerStateOnTransition: json["reportExoPlayerStateOnTransition"],
    manifestlessSequenceMethod: json["manifestlessSequenceMethod"],
    useLiveHeadWindow: json["useLiveHeadWindow"],
    enableDynamicHdrInHardware: json["enableDynamicHdrInHardware"],
    ultralowAudioQualityBandwidthThresholdBps: json["ultralowAudioQualityBandwidthThresholdBps"],
    retryLiveNetNocontentWithDelay: json["retryLiveNetNocontentWithDelay"],
    ignoreUnneededSeeksToLiveHead: json["ignoreUnneededSeeksToLiveHead"],
    drmMetricsQoeLoggingFraction: json["drmMetricsQoeLoggingFraction"]?.toDouble(),
    liveNetNocontentMaximumErrors: json["liveNetNocontentMaximumErrors"],
    slidingPercentileScalar: json["slidingPercentileScalar"],
    minAdaptiveVideoQuality: json["minAdaptiveVideoQuality"],
    platypusBackBufferDurationMs: json["platypusBackBufferDurationMs"],
  );

  Map<String, dynamic> toMap() => {
    "useExoPlayer": useExoPlayer,
    "useAdaptiveBitrate": useAdaptiveBitrate,
    "maxInitialByteRate": maxInitialByteRate,
    "minDurationForQualityIncreaseMs": minDurationForQualityIncreaseMs,
    "maxDurationForQualityDecreaseMs": maxDurationForQualityDecreaseMs,
    "minDurationToRetainAfterDiscardMs": minDurationToRetainAfterDiscardMs,
    "lowWatermarkMs": lowWatermarkMs,
    "highWatermarkMs": highWatermarkMs,
    "lowPoolLoad": lowPoolLoad,
    "highPoolLoad": highPoolLoad,
    "sufficientBandwidthOverhead": sufficientBandwidthOverhead,
    "bufferChunkSizeKb": bufferChunkSizeKb,
    "httpConnectTimeoutMs": httpConnectTimeoutMs,
    "httpReadTimeoutMs": httpReadTimeoutMs,
    "numAudioSegmentsPerFetch": numAudioSegmentsPerFetch,
    "numVideoSegmentsPerFetch": numVideoSegmentsPerFetch,
    "minDurationForPlaybackStartMs": minDurationForPlaybackStartMs,
    "enableExoplayerReuse": enableExoplayerReuse,
    "useRadioTypeForInitialQualitySelection": useRadioTypeForInitialQualitySelection,
    "blacklistFormatOnError": blacklistFormatOnError,
    "enableBandaidHttpDataSource": enableBandaidHttpDataSource,
    "httpLoadTimeoutMs": httpLoadTimeoutMs,
    "canPlayHdDrm": canPlayHdDrm,
    "videoBufferSegmentCount": videoBufferSegmentCount,
    "audioBufferSegmentCount": audioBufferSegmentCount,
    "useAbruptSplicing": useAbruptSplicing,
    "minRetryCount": minRetryCount,
    "minChunksNeededToPreferOffline": minChunksNeededToPreferOffline,
    "secondsToMaxAggressiveness": secondsToMaxAggressiveness,
    "enableSurfaceviewResizeWorkaround": enableSurfaceviewResizeWorkaround,
    "enableVp9IfThresholdsPass": enableVp9IfThresholdsPass,
    "matchQualityToViewportOnUnfullscreen": matchQualityToViewportOnUnfullscreen,
    "lowAudioQualityConnTypes": lowAudioQualityConnTypes == null ? [] : List<dynamic>.from(lowAudioQualityConnTypes!.map((x) => x)),
    "useDashForLiveStreams": useDashForLiveStreams,
    "enableLibvpxVideoTrackRenderer": enableLibvpxVideoTrackRenderer,
    "lowAudioQualityBandwidthThresholdBps": lowAudioQualityBandwidthThresholdBps,
    "enableVariableSpeedPlayback": enableVariableSpeedPlayback,
    "preferOnesieBufferedFormat": preferOnesieBufferedFormat,
    "minimumBandwidthSampleBytes": minimumBandwidthSampleBytes,
    "useDashForOtfAndCompletedLiveStreams": useDashForOtfAndCompletedLiveStreams,
    "disableCacheAwareVideoFormatEvaluation": disableCacheAwareVideoFormatEvaluation,
    "useLiveDvrForDashLiveStreams": useLiveDvrForDashLiveStreams,
    "cronetResetTimeoutOnRedirects": cronetResetTimeoutOnRedirects,
    "emitVideoDecoderChangeEvents": emitVideoDecoderChangeEvents,
    "onesieVideoBufferLoadTimeoutMs": onesieVideoBufferLoadTimeoutMs,
    "onesieVideoBufferReadTimeoutMs": onesieVideoBufferReadTimeoutMs,
    "libvpxEnableGl": libvpxEnableGl,
    "enableVp9EncryptedIfThresholdsPass": enableVp9EncryptedIfThresholdsPass,
    "enableOpus": enableOpus,
    "usePredictedBuffer": usePredictedBuffer,
    "maxReadAheadMediaTimeMs": maxReadAheadMediaTimeMs,
    "useMediaTimeCappedLoadControl": useMediaTimeCappedLoadControl,
    "allowCacheOverrideToLowerQualitiesWithinRange": allowCacheOverrideToLowerQualitiesWithinRange,
    "allowDroppingUndecodedFrames": allowDroppingUndecodedFrames,
    "minDurationForPlaybackRestartMs": minDurationForPlaybackRestartMs,
    "serverProvidedBandwidthHeader": serverProvidedBandwidthHeader,
    "liveOnlyPegStrategy": liveOnlyPegStrategy,
    "enableRedirectorHostFallback": enableRedirectorHostFallback,
    "enableHighlyAvailableFormatFallbackOnPcr": enableHighlyAvailableFormatFallbackOnPcr,
    "recordTrackRendererTimingEvents": recordTrackRendererTimingEvents,
    "minErrorsForRedirectorHostFallback": minErrorsForRedirectorHostFallback,
    "nonHardwareMediaCodecNames": nonHardwareMediaCodecNames == null ? [] : List<dynamic>.from(nonHardwareMediaCodecNames!.map((x) => x)),
    "enableVp9IfInHardware": enableVp9IfInHardware,
    "enableVp9EncryptedIfInHardware": enableVp9EncryptedIfInHardware,
    "useOpusMedAsLowQualityAudio": useOpusMedAsLowQualityAudio,
    "minErrorsForPcrFallback": minErrorsForPcrFallback,
    "useStickyRedirectHttpDataSource": useStickyRedirectHttpDataSource,
    "onlyVideoBandwidth": onlyVideoBandwidth,
    "useRedirectorOnNetworkChange": useRedirectorOnNetworkChange,
    "enableMaxReadaheadAbrThreshold": enableMaxReadaheadAbrThreshold,
    "cacheCheckDirectoryWritabilityOnce": cacheCheckDirectoryWritabilityOnce,
    "predictorType": predictorType,
    "slidingPercentile": slidingPercentile,
    "slidingWindowSize": slidingWindowSize,
    "maxFrameDropIntervalMs": maxFrameDropIntervalMs,
    "ignoreLoadTimeoutForFallback": ignoreLoadTimeoutForFallback,
    "serverBweMultiplier": serverBweMultiplier,
    "drmMaxKeyfetchDelayMs": drmMaxKeyfetchDelayMs,
    "maxResolutionForWhiteNoise": maxResolutionForWhiteNoise,
    "whiteNoiseRenderEffectMode": whiteNoiseRenderEffectMode,
    "enableLibvpxHdr": enableLibvpxHdr,
    "enableCacheAwareStreamSelection": enableCacheAwareStreamSelection,
    "useExoCronetDataSource": useExoCronetDataSource,
    "whiteNoiseScale": whiteNoiseScale,
    "whiteNoiseOffset": whiteNoiseOffset,
    "preventVideoFrameLaggingWithLibvpx": preventVideoFrameLaggingWithLibvpx,
    "enableMediaCodecHdr": enableMediaCodecHdr,
    "enableMediaCodecSwHdr": enableMediaCodecSwHdr,
    "liveOnlyWindowChunks": liveOnlyWindowChunks,
    "bearerMinDurationToRetainAfterDiscardMs": bearerMinDurationToRetainAfterDiscardMs == null ? [] : List<dynamic>.from(bearerMinDurationToRetainAfterDiscardMs!.map((x) => x)),
    "forceWidevineL3": forceWidevineL3,
    "useAverageBitrate": useAverageBitrate,
    "useMedialibAudioTrackRendererForLive": useMedialibAudioTrackRendererForLive,
    "useExoPlayerV2": useExoPlayerV2,
    "logMediaRequestEventsToCsi": logMediaRequestEventsToCsi,
    "onesieFixNonZeroStartTimeFormatSelection": onesieFixNonZeroStartTimeFormatSelection,
    "liveOnlyReadaheadStepSizeChunks": liveOnlyReadaheadStepSizeChunks,
    "liveOnlyBufferHealthHalfLifeSeconds": liveOnlyBufferHealthHalfLifeSeconds,
    "liveOnlyMinBufferHealthRatio": liveOnlyMinBufferHealthRatio,
    "liveOnlyMinLatencyToSeekRatio": liveOnlyMinLatencyToSeekRatio,
    "manifestlessPartialChunkStrategy": manifestlessPartialChunkStrategy,
    "ignoreViewportSizeWhenSticky": ignoreViewportSizeWhenSticky,
    "enableLibvpxFallback": enableLibvpxFallback,
    "disableLibvpxLoopFilter": disableLibvpxLoopFilter,
    "enableVpxMediaView": enableVpxMediaView,
    "hdrMinScreenBrightness": hdrMinScreenBrightness,
    "hdrMaxScreenBrightnessThreshold": hdrMaxScreenBrightnessThreshold,
    "onesieDataSourceAboveCacheDataSource": onesieDataSourceAboveCacheDataSource,
    "httpNonplayerLoadTimeoutMs": httpNonplayerLoadTimeoutMs,
    "numVideoSegmentsPerFetchStrategy": numVideoSegmentsPerFetchStrategy,
    "maxVideoDurationPerFetchMs": maxVideoDurationPerFetchMs,
    "maxVideoEstimatedLoadDurationMs": maxVideoEstimatedLoadDurationMs,
    "estimatedServerClockHalfLife": estimatedServerClockHalfLife,
    "estimatedServerClockStrictOffset": estimatedServerClockStrictOffset,
    "minReadAheadMediaTimeMs": minReadAheadMediaTimeMs,
    "readAheadGrowthRate": readAheadGrowthRate,
    "useDynamicReadAhead": useDynamicReadAhead,
    "useYtVodMediaSourceForV2": useYtVodMediaSourceForV2,
    "enableV2Gapless": enableV2Gapless,
    "useLiveHeadTimeMillis": useLiveHeadTimeMillis,
    "allowTrackSelectionWithUpdatedVideoItagsForExoV2": allowTrackSelectionWithUpdatedVideoItagsForExoV2,
    "maxAllowableTimeBeforeMediaTimeUpdateSec": maxAllowableTimeBeforeMediaTimeUpdateSec,
    "enableDynamicHdr": enableDynamicHdr,
    "v2PerformEarlyStreamSelection": v2PerformEarlyStreamSelection,
    "v2UsePlaybackStreamSelectionResult": v2UsePlaybackStreamSelectionResult,
    "v2MinTimeBetweenAbrReevaluationMs": v2MinTimeBetweenAbrReevaluationMs,
    "avoidReusePlaybackAcrossLoadvideos": avoidReusePlaybackAcrossLoadvideos,
    "enableInfiniteNetworkLoadingRetries": enableInfiniteNetworkLoadingRetries,
    "reportExoPlayerStateOnTransition": reportExoPlayerStateOnTransition,
    "manifestlessSequenceMethod": manifestlessSequenceMethod,
    "useLiveHeadWindow": useLiveHeadWindow,
    "enableDynamicHdrInHardware": enableDynamicHdrInHardware,
    "ultralowAudioQualityBandwidthThresholdBps": ultralowAudioQualityBandwidthThresholdBps,
    "retryLiveNetNocontentWithDelay": retryLiveNetNocontentWithDelay,
    "ignoreUnneededSeeksToLiveHead": ignoreUnneededSeeksToLiveHead,
    "drmMetricsQoeLoggingFraction": drmMetricsQoeLoggingFraction,
    "liveNetNocontentMaximumErrors": liveNetNocontentMaximumErrors,
    "slidingPercentileScalar": slidingPercentileScalar,
    "minAdaptiveVideoQuality": minAdaptiveVideoQuality,
    "platypusBackBufferDurationMs": platypusBackBufferDurationMs,
  };
}

class LidarSdkConfig {
  bool? enableActiveViewReporter;
  bool? useMediaTime;
  bool? sendTosMetrics;
  bool? usePlayerState;
  bool? enableIosAppStateCheck;
  bool? enableIsAndroidVideoAlwaysMeasurable;
  bool? enableActiveViewAudioMeasurementAndroid;

  LidarSdkConfig({
    this.enableActiveViewReporter,
    this.useMediaTime,
    this.sendTosMetrics,
    this.usePlayerState,
    this.enableIosAppStateCheck,
    this.enableIsAndroidVideoAlwaysMeasurable,
    this.enableActiveViewAudioMeasurementAndroid,
  });

  factory LidarSdkConfig.fromJson(String str) => LidarSdkConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory LidarSdkConfig.fromMap(Map<String, dynamic> json) => LidarSdkConfig(
    enableActiveViewReporter: json["enableActiveViewReporter"],
    useMediaTime: json["useMediaTime"],
    sendTosMetrics: json["sendTosMetrics"],
    usePlayerState: json["usePlayerState"],
    enableIosAppStateCheck: json["enableIosAppStateCheck"],
    enableIsAndroidVideoAlwaysMeasurable: json["enableIsAndroidVideoAlwaysMeasurable"],
    enableActiveViewAudioMeasurementAndroid: json["enableActiveViewAudioMeasurementAndroid"],
  );

  Map<String, dynamic> toMap() => {
    "enableActiveViewReporter": enableActiveViewReporter,
    "useMediaTime": useMediaTime,
    "sendTosMetrics": sendTosMetrics,
    "usePlayerState": usePlayerState,
    "enableIosAppStateCheck": enableIosAppStateCheck,
    "enableIsAndroidVideoAlwaysMeasurable": enableIsAndroidVideoAlwaysMeasurable,
    "enableActiveViewAudioMeasurementAndroid": enableActiveViewAudioMeasurementAndroid,
  };
}

class MediaCommonConfig {
  DynamicReadaheadConfig? dynamicReadaheadConfig;
  MediaUstreamerRequestConfig? mediaUstreamerRequestConfig;
  PredictedReadaheadConfig? predictedReadaheadConfig;
  MediaFetchRetryConfig? mediaFetchRetryConfig;
  int? mediaFetchMaximumServerErrors;
  int? mediaFetchMaximumNetworkErrors;
  int? mediaFetchMaximumErrors;
  ServerReadaheadConfig? serverReadaheadConfig;
  bool? useServerDrivenAbr;
  SabrClientConfig? sabrClientConfig;

  MediaCommonConfig({
    this.dynamicReadaheadConfig,
    this.mediaUstreamerRequestConfig,
    this.predictedReadaheadConfig,
    this.mediaFetchRetryConfig,
    this.mediaFetchMaximumServerErrors,
    this.mediaFetchMaximumNetworkErrors,
    this.mediaFetchMaximumErrors,
    this.serverReadaheadConfig,
    this.useServerDrivenAbr,
    this.sabrClientConfig,
  });

  factory MediaCommonConfig.fromJson(String str) => MediaCommonConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory MediaCommonConfig.fromMap(Map<String, dynamic> json) => MediaCommonConfig(
    dynamicReadaheadConfig: json["dynamicReadaheadConfig"] == null ? null : DynamicReadaheadConfig.fromMap(json["dynamicReadaheadConfig"]),
    mediaUstreamerRequestConfig: json["mediaUstreamerRequestConfig"] == null ? null : MediaUstreamerRequestConfig.fromMap(json["mediaUstreamerRequestConfig"]),
    predictedReadaheadConfig: json["predictedReadaheadConfig"] == null ? null : PredictedReadaheadConfig.fromMap(json["predictedReadaheadConfig"]),
    mediaFetchRetryConfig: json["mediaFetchRetryConfig"] == null ? null : MediaFetchRetryConfig.fromMap(json["mediaFetchRetryConfig"]),
    mediaFetchMaximumServerErrors: json["mediaFetchMaximumServerErrors"],
    mediaFetchMaximumNetworkErrors: json["mediaFetchMaximumNetworkErrors"],
    mediaFetchMaximumErrors: json["mediaFetchMaximumErrors"],
    serverReadaheadConfig: json["serverReadaheadConfig"] == null ? null : ServerReadaheadConfig.fromMap(json["serverReadaheadConfig"]),
    useServerDrivenAbr: json["useServerDrivenAbr"],
    sabrClientConfig: json["sabrClientConfig"] == null ? null : SabrClientConfig.fromMap(json["sabrClientConfig"]),
  );

  Map<String, dynamic> toMap() => {
    "dynamicReadaheadConfig": dynamicReadaheadConfig?.toMap(),
    "mediaUstreamerRequestConfig": mediaUstreamerRequestConfig?.toMap(),
    "predictedReadaheadConfig": predictedReadaheadConfig?.toMap(),
    "mediaFetchRetryConfig": mediaFetchRetryConfig?.toMap(),
    "mediaFetchMaximumServerErrors": mediaFetchMaximumServerErrors,
    "mediaFetchMaximumNetworkErrors": mediaFetchMaximumNetworkErrors,
    "mediaFetchMaximumErrors": mediaFetchMaximumErrors,
    "serverReadaheadConfig": serverReadaheadConfig?.toMap(),
    "useServerDrivenAbr": useServerDrivenAbr,
    "sabrClientConfig": sabrClientConfig?.toMap(),
  };
}

class DynamicReadaheadConfig {
  int? maxReadAheadMediaTimeMs;
  int? minReadAheadMediaTimeMs;
  int? readAheadGrowthRateMs;
  int? readAheadWatermarkMarginRatio;
  int? minReadAheadWatermarkMarginMs;
  int? maxReadAheadWatermarkMarginMs;
  bool? shouldIncorporateNetworkActiveState;

  DynamicReadaheadConfig({
    this.maxReadAheadMediaTimeMs,
    this.minReadAheadMediaTimeMs,
    this.readAheadGrowthRateMs,
    this.readAheadWatermarkMarginRatio,
    this.minReadAheadWatermarkMarginMs,
    this.maxReadAheadWatermarkMarginMs,
    this.shouldIncorporateNetworkActiveState,
  });

  factory DynamicReadaheadConfig.fromJson(String str) => DynamicReadaheadConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory DynamicReadaheadConfig.fromMap(Map<String, dynamic> json) => DynamicReadaheadConfig(
    maxReadAheadMediaTimeMs: json["maxReadAheadMediaTimeMs"],
    minReadAheadMediaTimeMs: json["minReadAheadMediaTimeMs"],
    readAheadGrowthRateMs: json["readAheadGrowthRateMs"],
    readAheadWatermarkMarginRatio: json["readAheadWatermarkMarginRatio"],
    minReadAheadWatermarkMarginMs: json["minReadAheadWatermarkMarginMs"],
    maxReadAheadWatermarkMarginMs: json["maxReadAheadWatermarkMarginMs"],
    shouldIncorporateNetworkActiveState: json["shouldIncorporateNetworkActiveState"],
  );

  Map<String, dynamic> toMap() => {
    "maxReadAheadMediaTimeMs": maxReadAheadMediaTimeMs,
    "minReadAheadMediaTimeMs": minReadAheadMediaTimeMs,
    "readAheadGrowthRateMs": readAheadGrowthRateMs,
    "readAheadWatermarkMarginRatio": readAheadWatermarkMarginRatio,
    "minReadAheadWatermarkMarginMs": minReadAheadWatermarkMarginMs,
    "maxReadAheadWatermarkMarginMs": maxReadAheadWatermarkMarginMs,
    "shouldIncorporateNetworkActiveState": shouldIncorporateNetworkActiveState,
  };
}

class MediaFetchRetryConfig {
  int? initialDelayMs;
  double? backoffFactor;
  int? maximumDelayMs;
  double? jitterFactor;

  MediaFetchRetryConfig({
    this.initialDelayMs,
    this.backoffFactor,
    this.maximumDelayMs,
    this.jitterFactor,
  });

  factory MediaFetchRetryConfig.fromJson(String str) => MediaFetchRetryConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory MediaFetchRetryConfig.fromMap(Map<String, dynamic> json) => MediaFetchRetryConfig(
    initialDelayMs: json["initialDelayMs"],
    backoffFactor: json["backoffFactor"]?.toDouble(),
    maximumDelayMs: json["maximumDelayMs"],
    jitterFactor: json["jitterFactor"]?.toDouble(),
  );

  Map<String, dynamic> toMap() => {
    "initialDelayMs": initialDelayMs,
    "backoffFactor": backoffFactor,
    "maximumDelayMs": maximumDelayMs,
    "jitterFactor": jitterFactor,
  };
}

class MediaUstreamerRequestConfig {
  bool? enableVideoPlaybackRequest;
  String? videoPlaybackUstreamerConfig;
  bool? videoPlaybackPostEmptyBody;
  bool? isVideoPlaybackRequestIdempotent;

  MediaUstreamerRequestConfig({
    this.enableVideoPlaybackRequest,
    this.videoPlaybackUstreamerConfig,
    this.videoPlaybackPostEmptyBody,
    this.isVideoPlaybackRequestIdempotent,
  });

  factory MediaUstreamerRequestConfig.fromJson(String str) => MediaUstreamerRequestConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory MediaUstreamerRequestConfig.fromMap(Map<String, dynamic> json) => MediaUstreamerRequestConfig(
    enableVideoPlaybackRequest: json["enableVideoPlaybackRequest"],
    videoPlaybackUstreamerConfig: json["videoPlaybackUstreamerConfig"],
    videoPlaybackPostEmptyBody: json["videoPlaybackPostEmptyBody"],
    isVideoPlaybackRequestIdempotent: json["isVideoPlaybackRequestIdempotent"],
  );

  Map<String, dynamic> toMap() => {
    "enableVideoPlaybackRequest": enableVideoPlaybackRequest,
    "videoPlaybackUstreamerConfig": videoPlaybackUstreamerConfig,
    "videoPlaybackPostEmptyBody": videoPlaybackPostEmptyBody,
    "isVideoPlaybackRequestIdempotent": isVideoPlaybackRequestIdempotent,
  };
}

class PredictedReadaheadConfig {
  int? minReadaheadMs;
  int? maxReadaheadMs;

  PredictedReadaheadConfig({
    this.minReadaheadMs,
    this.maxReadaheadMs,
  });

  factory PredictedReadaheadConfig.fromJson(String str) => PredictedReadaheadConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory PredictedReadaheadConfig.fromMap(Map<String, dynamic> json) => PredictedReadaheadConfig(
    minReadaheadMs: json["minReadaheadMs"],
    maxReadaheadMs: json["maxReadaheadMs"],
  );

  Map<String, dynamic> toMap() => {
    "minReadaheadMs": minReadaheadMs,
    "maxReadaheadMs": maxReadaheadMs,
  };
}

class SabrClientConfig {
  int? defaultBackOffTimeMs;
  bool? enableHostFallback;
  int? primaryProbingDelayMs;
  int? maxFailureAttemptsBeforeFallback;

  SabrClientConfig({
    this.defaultBackOffTimeMs,
    this.enableHostFallback,
    this.primaryProbingDelayMs,
    this.maxFailureAttemptsBeforeFallback,
  });

  factory SabrClientConfig.fromJson(String str) => SabrClientConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory SabrClientConfig.fromMap(Map<String, dynamic> json) => SabrClientConfig(
    defaultBackOffTimeMs: json["defaultBackOffTimeMs"],
    enableHostFallback: json["enableHostFallback"],
    primaryProbingDelayMs: json["primaryProbingDelayMs"],
    maxFailureAttemptsBeforeFallback: json["maxFailureAttemptsBeforeFallback"],
  );

  Map<String, dynamic> toMap() => {
    "defaultBackOffTimeMs": defaultBackOffTimeMs,
    "enableHostFallback": enableHostFallback,
    "primaryProbingDelayMs": primaryProbingDelayMs,
    "maxFailureAttemptsBeforeFallback": maxFailureAttemptsBeforeFallback,
  };
}

class ServerReadaheadConfig {
  bool? enable;
  NextRequestPolicy? nextRequestPolicy;

  ServerReadaheadConfig({
    this.enable,
    this.nextRequestPolicy,
  });

  factory ServerReadaheadConfig.fromJson(String str) => ServerReadaheadConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory ServerReadaheadConfig.fromMap(Map<String, dynamic> json) => ServerReadaheadConfig(
    enable: json["enable"],
    nextRequestPolicy: json["nextRequestPolicy"] == null ? null : NextRequestPolicy.fromMap(json["nextRequestPolicy"]),
  );

  Map<String, dynamic> toMap() => {
    "enable": enable,
    "nextRequestPolicy": nextRequestPolicy?.toMap(),
  };
}

class NextRequestPolicy {
  int? targetAudioReadaheadMs;
  int? targetVideoReadaheadMs;

  NextRequestPolicy({
    this.targetAudioReadaheadMs,
    this.targetVideoReadaheadMs,
  });

  factory NextRequestPolicy.fromJson(String str) => NextRequestPolicy.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory NextRequestPolicy.fromMap(Map<String, dynamic> json) => NextRequestPolicy(
    targetAudioReadaheadMs: json["targetAudioReadaheadMs"],
    targetVideoReadaheadMs: json["targetVideoReadaheadMs"],
  );

  Map<String, dynamic> toMap() => {
    "targetAudioReadaheadMs": targetAudioReadaheadMs,
    "targetVideoReadaheadMs": targetVideoReadaheadMs,
  };
}

class NetworkProtocolConfig {
  bool? useQuic;

  NetworkProtocolConfig({
    this.useQuic,
  });

  factory NetworkProtocolConfig.fromJson(String str) => NetworkProtocolConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory NetworkProtocolConfig.fromMap(Map<String, dynamic> json) => NetworkProtocolConfig(
    useQuic: json["useQuic"],
  );

  Map<String, dynamic> toMap() => {
    "useQuic": useQuic,
  };
}

class PlayerRestorationConfig {
  bool? restoreIntoStoppedState;

  PlayerRestorationConfig({
    this.restoreIntoStoppedState,
  });

  factory PlayerRestorationConfig.fromJson(String str) => PlayerRestorationConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory PlayerRestorationConfig.fromMap(Map<String, dynamic> json) => PlayerRestorationConfig(
    restoreIntoStoppedState: json["restoreIntoStoppedState"],
  );

  Map<String, dynamic> toMap() => {
    "restoreIntoStoppedState": restoreIntoStoppedState,
  };
}

class RetryConfig {
  List<String>? retryEligibleErrors;
  int? retryUnderSameConditionAttempts;
  int? retryWithNewSurfaceAttempts;
  bool? progressiveFallbackOnNonNetworkErrors;
  bool? l3FallbackOnDrmErrors;
  bool? retryAfterCacheRemoval;
  bool? widevineL3EnforcedFallbackOnDrmErrors;
  bool? exoProxyableFormatFallback;
  int? maxPlayerRetriesWhenNetworkUnavailable;
  bool? suppressFatalErrorAfterStop;
  bool? fallbackToSwDecoderOnFormatDecodeError;

  RetryConfig({
    this.retryEligibleErrors,
    this.retryUnderSameConditionAttempts,
    this.retryWithNewSurfaceAttempts,
    this.progressiveFallbackOnNonNetworkErrors,
    this.l3FallbackOnDrmErrors,
    this.retryAfterCacheRemoval,
    this.widevineL3EnforcedFallbackOnDrmErrors,
    this.exoProxyableFormatFallback,
    this.maxPlayerRetriesWhenNetworkUnavailable,
    this.suppressFatalErrorAfterStop,
    this.fallbackToSwDecoderOnFormatDecodeError,
  });

  factory RetryConfig.fromJson(String str) => RetryConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory RetryConfig.fromMap(Map<String, dynamic> json) => RetryConfig(
    retryEligibleErrors: json["retryEligibleErrors"] == null ? [] : List<String>.from(json["retryEligibleErrors"]!.map((x) => x)),
    retryUnderSameConditionAttempts: json["retryUnderSameConditionAttempts"],
    retryWithNewSurfaceAttempts: json["retryWithNewSurfaceAttempts"],
    progressiveFallbackOnNonNetworkErrors: json["progressiveFallbackOnNonNetworkErrors"],
    l3FallbackOnDrmErrors: json["l3FallbackOnDrmErrors"],
    retryAfterCacheRemoval: json["retryAfterCacheRemoval"],
    widevineL3EnforcedFallbackOnDrmErrors: json["widevineL3EnforcedFallbackOnDrmErrors"],
    exoProxyableFormatFallback: json["exoProxyableFormatFallback"],
    maxPlayerRetriesWhenNetworkUnavailable: json["maxPlayerRetriesWhenNetworkUnavailable"],
    suppressFatalErrorAfterStop: json["suppressFatalErrorAfterStop"],
    fallbackToSwDecoderOnFormatDecodeError: json["fallbackToSwDecoderOnFormatDecodeError"],
  );

  Map<String, dynamic> toMap() => {
    "retryEligibleErrors": retryEligibleErrors == null ? [] : List<dynamic>.from(retryEligibleErrors!.map((x) => x)),
    "retryUnderSameConditionAttempts": retryUnderSameConditionAttempts,
    "retryWithNewSurfaceAttempts": retryWithNewSurfaceAttempts,
    "progressiveFallbackOnNonNetworkErrors": progressiveFallbackOnNonNetworkErrors,
    "l3FallbackOnDrmErrors": l3FallbackOnDrmErrors,
    "retryAfterCacheRemoval": retryAfterCacheRemoval,
    "widevineL3EnforcedFallbackOnDrmErrors": widevineL3EnforcedFallbackOnDrmErrors,
    "exoProxyableFormatFallback": exoProxyableFormatFallback,
    "maxPlayerRetriesWhenNetworkUnavailable": maxPlayerRetriesWhenNetworkUnavailable,
    "suppressFatalErrorAfterStop": suppressFatalErrorAfterStop,
    "fallbackToSwDecoderOnFormatDecodeError": fallbackToSwDecoderOnFormatDecodeError,
  };
}

class TaskCoordinatorConfig {
  int? prefetchCoordinatorBufferedPositionMillisRelease;
  int? prefetchCoordinatorBufferedPositionMillisPause;

  TaskCoordinatorConfig({
    this.prefetchCoordinatorBufferedPositionMillisRelease,
    this.prefetchCoordinatorBufferedPositionMillisPause,
  });

  factory TaskCoordinatorConfig.fromJson(String str) => TaskCoordinatorConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory TaskCoordinatorConfig.fromMap(Map<String, dynamic> json) => TaskCoordinatorConfig(
    prefetchCoordinatorBufferedPositionMillisRelease: json["prefetchCoordinatorBufferedPositionMillisRelease"],
    prefetchCoordinatorBufferedPositionMillisPause: json["prefetchCoordinatorBufferedPositionMillisPause"],
  );

  Map<String, dynamic> toMap() => {
    "prefetchCoordinatorBufferedPositionMillisRelease": prefetchCoordinatorBufferedPositionMillisRelease,
    "prefetchCoordinatorBufferedPositionMillisPause": prefetchCoordinatorBufferedPositionMillisPause,
  };
}

class VariableSpeedConfig {
  bool? showVariableSpeedDisabledDialog;

  VariableSpeedConfig({
    this.showVariableSpeedDisabledDialog,
  });

  factory VariableSpeedConfig.fromJson(String str) => VariableSpeedConfig.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory VariableSpeedConfig.fromMap(Map<String, dynamic> json) => VariableSpeedConfig(
    showVariableSpeedDisabledDialog: json["showVariableSpeedDisabledDialog"],
  );

  Map<String, dynamic> toMap() => {
    "showVariableSpeedDisabledDialog": showVariableSpeedDisabledDialog,
  };
}

class ResponseContext {
  String? visitorData;
  List<ServiceTrackingParam>? serviceTrackingParams;
  int? maxAgeSeconds;

  ResponseContext({
    this.visitorData,
    this.serviceTrackingParams,
    this.maxAgeSeconds,
  });

  factory ResponseContext.fromJson(String str) => ResponseContext.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory ResponseContext.fromMap(Map<String, dynamic> json) => ResponseContext(
    visitorData: json["visitorData"],
    serviceTrackingParams: json["serviceTrackingParams"] == null ? [] : List<ServiceTrackingParam>.from(json["serviceTrackingParams"]!.map((x) => ServiceTrackingParam.fromMap(x))),
    maxAgeSeconds: json["maxAgeSeconds"],
  );

  Map<String, dynamic> toMap() => {
    "visitorData": visitorData,
    "serviceTrackingParams": serviceTrackingParams == null ? [] : List<dynamic>.from(serviceTrackingParams!.map((x) => x.toMap())),
    "maxAgeSeconds": maxAgeSeconds,
  };
}

class ServiceTrackingParam {
  String? service;
  List<Param>? params;

  ServiceTrackingParam({
    this.service,
    this.params,
  });

  factory ServiceTrackingParam.fromJson(String str) => ServiceTrackingParam.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory ServiceTrackingParam.fromMap(Map<String, dynamic> json) => ServiceTrackingParam(
    service: json["service"],
    params: json["params"] == null ? [] : List<Param>.from(json["params"]!.map((x) => Param.fromMap(x))),
  );

  Map<String, dynamic> toMap() => {
    "service": service,
    "params": params == null ? [] : List<dynamic>.from(params!.map((x) => x.toMap())),
  };
}

class Param {
  String? key;
  String? value;

  Param({
    this.key,
    this.value,
  });

  factory Param.fromJson(String str) => Param.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory Param.fromMap(Map<String, dynamic> json) => Param(
    key: json["key"],
    value: json["value"],
  );

  Map<String, dynamic> toMap() => {
    "key": key,
    "value": value,
  };
}

class Storyboards {
  PlayerStoryboardSpecRenderer? playerStoryboardSpecRenderer;

  Storyboards({
    this.playerStoryboardSpecRenderer,
  });

  factory Storyboards.fromJson(String str) => Storyboards.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory Storyboards.fromMap(Map<String, dynamic> json) => Storyboards(
    playerStoryboardSpecRenderer: json["playerStoryboardSpecRenderer"] == null ? null : PlayerStoryboardSpecRenderer.fromMap(json["playerStoryboardSpecRenderer"]),
  );

  Map<String, dynamic> toMap() => {
    "playerStoryboardSpecRenderer": playerStoryboardSpecRenderer?.toMap(),
  };
}

class PlayerStoryboardSpecRenderer {
  String? spec;
  int? recommendedLevel;

  PlayerStoryboardSpecRenderer({
    this.spec,
    this.recommendedLevel,
  });

  factory PlayerStoryboardSpecRenderer.fromJson(String str) => PlayerStoryboardSpecRenderer.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory PlayerStoryboardSpecRenderer.fromMap(Map<String, dynamic> json) => PlayerStoryboardSpecRenderer(
    spec: json["spec"],
    recommendedLevel: json["recommendedLevel"],
  );

  Map<String, dynamic> toMap() => {
    "spec": spec,
    "recommendedLevel": recommendedLevel,
  };
}

class StreamingData {
  String? expiresInSeconds;
  List<Format>? formats;
  List<AdaptiveFormat>? adaptiveFormats;

  StreamingData({
    this.expiresInSeconds,
    this.formats,
    this.adaptiveFormats,
  });

  factory StreamingData.fromJson(String str) => StreamingData.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory StreamingData.fromMap(Map<String, dynamic> json) => StreamingData(
    expiresInSeconds: json["expiresInSeconds"],
    formats: json["formats"] == null ? [] : List<Format>.from(json["formats"]!.map((x) => Format.fromMap(x))),
    adaptiveFormats: json["adaptiveFormats"] == null ? [] : List<AdaptiveFormat>.from(json["adaptiveFormats"]!.map((x) => AdaptiveFormat.fromMap(x))),
  );

  Map<String, dynamic> toMap() => {
    "expiresInSeconds": expiresInSeconds,
    "formats": formats == null ? [] : List<dynamic>.from(formats!.map((x) => x.toMap())),
    "adaptiveFormats": adaptiveFormats == null ? [] : List<dynamic>.from(adaptiveFormats!.map((x) => x.toMap())),
  };
}

class AdaptiveFormat {
  int? itag;
  String? url;
  String? mimeType;
  int? bitrate;
  int? width;
  int? height;
  Range? initRange;
  Range? indexRange;
  String? lastModified;
  String? contentLength;
  String? quality;
  int? fps;
  String? qualityLabel;
  String? projectionType;
  int? averageBitrate;
  String? approxDurationMs;
  ColorInfo? colorInfo;
  bool? highReplication;
  String? audioQuality;
  String? audioSampleRate;
  int? audioChannels;
  double? loudnessDb;

  AdaptiveFormat({
    this.itag,
    this.url,
    this.mimeType,
    this.bitrate,
    this.width,
    this.height,
    this.initRange,
    this.indexRange,
    this.lastModified,
    this.contentLength,
    this.quality,
    this.fps,
    this.qualityLabel,
    this.projectionType,
    this.averageBitrate,
    this.approxDurationMs,
    this.colorInfo,
    this.highReplication,
    this.audioQuality,
    this.audioSampleRate,
    this.audioChannels,
    this.loudnessDb,
  });

  factory AdaptiveFormat.fromJson(String str) => AdaptiveFormat.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory AdaptiveFormat.fromMap(Map<String, dynamic> json) => AdaptiveFormat(
    itag: json["itag"],
    url: json["url"],
    mimeType: json["mimeType"],
    bitrate: json["bitrate"],
    width: json["width"],
    height: json["height"],
    initRange: json["initRange"] == null ? null : Range.fromMap(json["initRange"]),
    indexRange: json["indexRange"] == null ? null : Range.fromMap(json["indexRange"]),
    lastModified: json["lastModified"],
    contentLength: json["contentLength"],
    quality: json["quality"],
    fps: json["fps"],
    qualityLabel: json["qualityLabel"],
    projectionType: json["projectionType"],
    averageBitrate: json["averageBitrate"],
    approxDurationMs: json["approxDurationMs"],
    colorInfo: json["colorInfo"] == null ? null : ColorInfo.fromMap(json["colorInfo"]),
    highReplication: json["highReplication"],
    audioQuality: json["audioQuality"],
    audioSampleRate: json["audioSampleRate"],
    audioChannels: json["audioChannels"],
    loudnessDb: json["loudnessDb"]?.toDouble(),
  );

  Map<String, dynamic> toMap() => {
    "itag": itag,
    "url": url,
    "mimeType": mimeType,
    "bitrate": bitrate,
    "width": width,
    "height": height,
    "initRange": initRange?.toMap(),
    "indexRange": indexRange?.toMap(),
    "lastModified": lastModified,
    "contentLength": contentLength,
    "quality": quality,
    "fps": fps,
    "qualityLabel": qualityLabel,
    "projectionType": projectionType,
    "averageBitrate": averageBitrate,
    "approxDurationMs": approxDurationMs,
    "colorInfo": colorInfo?.toMap(),
    "highReplication": highReplication,
    "audioQuality": audioQuality,
    "audioSampleRate": audioSampleRate,
    "audioChannels": audioChannels,
    "loudnessDb": loudnessDb,
  };
}

class ColorInfo {
  String? primaries;
  String? transferCharacteristics;
  String? matrixCoefficients;

  ColorInfo({
    this.primaries,
    this.transferCharacteristics,
    this.matrixCoefficients,
  });

  factory ColorInfo.fromJson(String str) => ColorInfo.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory ColorInfo.fromMap(Map<String, dynamic> json) => ColorInfo(
    primaries: json["primaries"],
    transferCharacteristics: json["transferCharacteristics"],
    matrixCoefficients: json["matrixCoefficients"],
  );

  Map<String, dynamic> toMap() => {
    "primaries": primaries,
    "transferCharacteristics": transferCharacteristics,
    "matrixCoefficients": matrixCoefficients,
  };
}

class Range {
  String? start;
  String? end;

  Range({
    this.start,
    this.end,
  });

  factory Range.fromJson(String str) => Range.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory Range.fromMap(Map<String, dynamic> json) => Range(
    start: json["start"],
    end: json["end"],
  );

  Map<String, dynamic> toMap() => {
    "start": start,
    "end": end,
  };
}

class Format {
  int? itag;
  String? url;
  String? mimeType;
  int? bitrate;
  int? width;
  int? height;
  String? lastModified;
  String? quality;
  int? fps;
  String? qualityLabel;
  String? projectionType;
  String? audioQuality;
  String? approxDurationMs;
  String? audioSampleRate;
  int? audioChannels;

  Format({
    this.itag,
    this.url,
    this.mimeType,
    this.bitrate,
    this.width,
    this.height,
    this.lastModified,
    this.quality,
    this.fps,
    this.qualityLabel,
    this.projectionType,
    this.audioQuality,
    this.approxDurationMs,
    this.audioSampleRate,
    this.audioChannels,
  });

  factory Format.fromJson(String str) => Format.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory Format.fromMap(Map<String, dynamic> json) => Format(
    itag: json["itag"],
    url: json["url"],
    mimeType: json["mimeType"],
    bitrate: json["bitrate"],
    width: json["width"],
    height: json["height"],
    lastModified: json["lastModified"],
    quality: json["quality"],
    fps: json["fps"],
    qualityLabel: json["qualityLabel"],
    projectionType: json["projectionType"],
    audioQuality: json["audioQuality"],
    approxDurationMs: json["approxDurationMs"],
    audioSampleRate: json["audioSampleRate"],
    audioChannels: json["audioChannels"],
  );

  Map<String, dynamic> toMap() => {
    "itag": itag,
    "url": url,
    "mimeType": mimeType,
    "bitrate": bitrate,
    "width": width,
    "height": height,
    "lastModified": lastModified,
    "quality": quality,
    "fps": fps,
    "qualityLabel": qualityLabel,
    "projectionType": projectionType,
    "audioQuality": audioQuality,
    "approxDurationMs": approxDurationMs,
    "audioSampleRate": audioSampleRate,
    "audioChannels": audioChannels,
  };
}

class VideoDetails {
  String? videoId;
  String? title;
  String? lengthSeconds;
  String? channelId;
  bool? isOwnerViewing;
  bool? isCrawlable;
  VideoDetailsThumbnail? thumbnail;
  bool? allowRatings;
  String? viewCount;
  String? author;
  bool? isPrivate;
  bool? isUnpluggedCorpus;
  String? musicVideoType;
  bool? isLiveContent;

  VideoDetails({
    this.videoId,
    this.title,
    this.lengthSeconds,
    this.channelId,
    this.isOwnerViewing,
    this.isCrawlable,
    this.thumbnail,
    this.allowRatings,
    this.viewCount,
    this.author,
    this.isPrivate,
    this.isUnpluggedCorpus,
    this.musicVideoType,
    this.isLiveContent,
  });

  factory VideoDetails.fromJson(String str) => VideoDetails.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory VideoDetails.fromMap(Map<String, dynamic> json) => VideoDetails(
    videoId: json["videoId"],
    title: json["title"],
    lengthSeconds: json["lengthSeconds"],
    channelId: json["channelId"],
    isOwnerViewing: json["isOwnerViewing"],
    isCrawlable: json["isCrawlable"],
    thumbnail: json["thumbnail"] == null ? null : VideoDetailsThumbnail.fromMap(json["thumbnail"]),
    allowRatings: json["allowRatings"],
    viewCount: json["viewCount"],
    author: json["author"],
    isPrivate: json["isPrivate"],
    isUnpluggedCorpus: json["isUnpluggedCorpus"],
    musicVideoType: json["musicVideoType"],
    isLiveContent: json["isLiveContent"],
  );

  Map<String, dynamic> toMap() => {
    "videoId": videoId,
    "title": title,
    "lengthSeconds": lengthSeconds,
    "channelId": channelId,
    "isOwnerViewing": isOwnerViewing,
    "isCrawlable": isCrawlable,
    "thumbnail": thumbnail?.toMap(),
    "allowRatings": allowRatings,
    "viewCount": viewCount,
    "author": author,
    "isPrivate": isPrivate,
    "isUnpluggedCorpus": isUnpluggedCorpus,
    "musicVideoType": musicVideoType,
    "isLiveContent": isLiveContent,
  };
}

class VideoDetailsThumbnail {
  List<ThumbnailElement>? thumbnails;

  VideoDetailsThumbnail({
    this.thumbnails,
  });

  factory VideoDetailsThumbnail.fromJson(String str) => VideoDetailsThumbnail.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory VideoDetailsThumbnail.fromMap(Map<String, dynamic> json) => VideoDetailsThumbnail(
    thumbnails: json["thumbnails"] == null ? [] : List<ThumbnailElement>.from(json["thumbnails"]!.map((x) => ThumbnailElement.fromMap(x))),
  );

  Map<String, dynamic> toMap() => {
    "thumbnails": thumbnails == null ? [] : List<dynamic>.from(thumbnails!.map((x) => x.toMap())),
  };
}

class ThumbnailElement {
  String? url;
  int? width;
  int? height;

  ThumbnailElement({
    this.url,
    this.width,
    this.height,
  });

  factory ThumbnailElement.fromJson(String str) => ThumbnailElement.fromMap(json.decode(str));

  String toJson() => json.encode(toMap());

  factory ThumbnailElement.fromMap(Map<String, dynamic> json) => ThumbnailElement(
    url: json["url"],
    width: json["width"],
    height: json["height"],
  );

  Map<String, dynamic> toMap() => {
    "url": url,
    "width": width,
    "height": height,
  };
}
