X264 Encoding Suggestions

本文提供了使用x264编码器的最佳实践,包括一般提示、命令行建议、VBV编码、Blu-ray编码及QuickTime兼容性等内容。旨在帮助用户针对不同应用场景选择合适的编码参数。


Contents

[hide]

General Tips

  • Don't use x264 as a replacement for a denoising filter. Ensure that your input looks like what you want as output (ignoring the loss in quality from compression). Doing anything else causes x264 to run less efficiently.
  • If you aren't seeing 100% CPU usage while encoding, the problem may lie with your input:
    • Raw YUV input can easily be constrained by your IO system's speed. The size of a raw frame can be calculated as: width * height * bitdepth (12 for YV12) / 8 (bits -> bytes) / 1024 (bytes -> kbytes) / 1024 (kbytes -> mbytes).
    • Avisynth scripts run in a single thread. Some filters can spawn extra threads for themselves but this doesn't give huge gains.
    • ffmpeg (and therefore ffms2) is only supported as a single-threaded decoder in x264.
  • The Flash h.264 decoder (and others) didn't support weighted P-frame prediction (--weightp) until version 10.1, which still isn't widely deployed (>90%) at time of writing. Set --weightp 0 when encoding for Flash if this is still the case.
  • Apple's QuickTime Player has various decoding issues, especially related to reference frame count. See the QuickTime encoding suggestions if you want to maintain QuickTime compatibility, and you should since they make up a large portion of computer users.

Commandline Suggestions

You can divide x264 settings into three groups:

1. Those you should touch directly

Things like --bitrate, --keyint, --slices and so forth. They depend on the requirements of your decoder and thus are ignored by x264's preset system.

2. Those you should touch via the preset system

Before the preset system existed people wrote giant commandlines specifying every option by hand. There were arguments over whether --subme 9 with --me hex was better or worse than --subme 7 with --me tesa. Crazy! Do your part to bury these memories by using --preset, --tune and --profile.

3. Those you should avoid remembering exist

--qcomp, --scenecut, and so on. Settings that probably should be built-in constants now. Their use in contemporary commandlines serve no purpose other than causing pain among readers when asking for help. Seriously, people-tweaking-obscure-parameters-because-of-a-hazy-belief-it-helps, knock it off.

VBV Encoding

The VBV (Video Buffer Verifier) system in x264 is used to constrain the output bitrate so it is suitable for streaming in a bandwidth constrained environment.

The h.264 VBV model is based around the idea of a "VBV buffer" on the decoder side. As the h.264 stream is downloaded by the client it's stored in the VBV buffer. A frame must be fully downloaded into the VBV buffer before it can be decoded.

x264 has three options that control the VBV buffer:

  1. The buffer's size is specified in kbit with --vbv-bufsize,
  2. The rate at which the buffer fills is specified in kbit/sec by --vbv-maxrate,
  3. The proportion of the buffer that must be filled before playback can start is specified by --vbv-init.

When using VBV, you always need to set the first two options and should never need to set the last one.

Examples

Example 1

Scenario: Encoding a movie to a file on your hard drive to play at a later date.

Suggestion: Do not specify any VBV settings. Your hard drive has a fast enough transfer rate that there's no need to specify any VBV constraints.

Example 2

Scenario: Encoding a video that's suitable for muxing to a Blu-ray compatible file.

Suggestion: The Blu-ray specification specifies a 40 Mbit maximum data rate (for the video) and a 30 Mbit buffer. So, specify --bluray-compat --vbv-maxrate 40000 --vbv-bufsize 30000.

Note: x264 needs more options to output a fully compliant Blu-ray file. But these options are all you need for VBV compliancy.

Example 3

Scenario: Streaming a video via Flash on a website, like Youtube.

Suggestion: You want the video to start very quickly, so there can't be more than (say) 0.5 seconds of buffering. You set a minimum connection speed requirement for viewers of 512kbit/sec. Assume that 90% of that bandwidth will be usable by your site, and that 96kbit/sec will be used by audio, which leaves 364kbit/sec for x264. So, specify --vbv-maxrate 364 --vbv-buffer 182.

Note: There are more factors than just the video VBV settings when looking at the start delay for online streaming. The above example is for a perfect world where these factors don't exist.

Blu-ray Encoding

Someone else (kierank) has done all the hard work, you can find full instructions on creating Blu-ray compliant files with x264 here. The short answer for 1080p encoding is as follows:

x264 --bluray-compat --bitrate X --preset veryslow --weightp 0 --bframes 3 --nal-hrd vbr --vbv-maxrate 40000 \
    --vbv-bufsize 30000 --level 4.1 --keyint X --b-pyramid strict --slices 4 --fake-interlaced \
    --aud --colorprim "bt709" --transfer "bt709" --colormatrix "bt709" --sar 1:1 \
    --pass 1 -o output.file input.file
x264 --bluray-compat  --bitrate X --preset veryslow --weightp 0 --bframes 3 --nal-hrd vbr --vbv-maxrate 40000 \
    --vbv-bufsize 30000 --level 4.1 --keyint X --b-pyramid strict --slices 4 --fake-interlaced \
    --aud --colorprim "bt709" --transfer "bt709" --colormatrix "bt709" --sar 1:1 \
    --pass 2 -o output.file input.file

Set keyint to your fps. Use a faster preset if desired. Add a --tune parameter if desired. --weightp is disabled because some hardware decoders have problems with it, not because it's mandated by the Blu-ray spec.

Encoder latency

Depending on the encoder settings you configure, x264 will keep an internal buffer of frames to improve quality. When you're just encoding a file offline this is irrelevant, but if you're working in a broadcast or streaming environment this delay can be unacceptable.

You can calculate the number of frames x264 buffer (the encoder latency) using the following pseudocode. If you use the libx264 API, see also x264_encoder_delayed_frames.

delay = 0

if b-adapt=2 and not (nopass or pass2):
    delay = MAX(bframes,3)*4
else:
    delay = bframes

if mb-tree or vbv:
     delay = MAX(delay,rc_lookahead)

if not sliced-threads:
    delay = delay + threads - 1

delay = delay + sync-lookahead

if vbv and (vfr-input or abr or pass1:
    delay = delay + 1

Reducing x264's latency is possible, but reduces quality. If you want no latency, set --tune zerolatency. If you can handle even a little latency (ie under 1 second), it is well worth tuning the options to allow this. Here is a series of steps you can follow to incrementally reduce latency. Stop when your latency is low enough:

  1. Start with defaults
  2. Kill sync-lookahead
  3. Drop rc-lookahead to no less than ~10
  4. Drop threads to a lower value (i.e. say 6 instead of 12)
  5. Use sliced threads
  6. Disable rc-lookahead
  7. Disable b-frames
  8. Now you're at --tune zerolatency

QuickTime-compatible Encoding

There is a lot of very outdated misinformation surrounding how to encode h.264 videos that play perfectly in QuickTime. For instance that "QT supports only 1 B-Frame" and "QT doesn't support pyramidal B-Frames" which are both false as of QuickTime Player 7.7. There also used to exist a qpmin/dct bug in early versions of QuickTime Player where the player couldn't deal with a low quantizer (below 4) combined 8x8 DCT Transforms; however, that has been fixed as of QuickTime Player X.

QuickTime Player X compatibility

The Apple h.264 decoder component released with the launch of QuickTime Player X is a pretty good decoder and has only one big remaining bug. However, before we go on, you might wonder about all those people that are stuck on older versions of QuickTime Player, refusing to upgrade to QTX. That is no problem at all, because the actual decoder that is used systemwide by OS X (including by QuickTime) is a separate component from the player, and will have been updated through Software Updates even though they may not have downloaded the actual player update. So, any time we refer to QuickTime Player X, assume that anyone with 10.6 Snow Leopard or higher has that bug-fixed Apple h.264 decoder component, even if they don't specifically have QTX.

There is now just a single remaining major Apple h.264 decoder flaw:

  • A high number of reference frames (15 or more, to be precise) combined with a high number of B-Frames produces blocky, distorted video output. This is an issue you will encounter with the "veryslow" preset, since it uses up to 16 reference frames.

Solution:

  • Limit the number of reference frames to any number between 1-14. Look up the acceptable number of reference frames for your desired h.264 level and video resolution and make sure never to exceed that value or 14, whichever comes first. However, there is rarely any point in exceeding 5 reference frames anyway, and 4 frames is the maximum allowed for 1080p content in the most common levels, so a good choice is to simply pick 4 reference frames for all your encodes regardless of video resolution: --ref 4 (For Level 5+ encodes, you may want to refer to the level specifications and pick a higher number as long as you don't exceed 14.)

QuickTime Player 7.7 compatibility

Any operating system that has the option of installing QuickTime Player X will have the updated QTX decoder. That sadly means only OS X 10.6 Snow Leopard users and higher. So, if you want 10.5 Leopard users to be able to play your videos, you'll have to read this section as well since they are stuck on QuickTime Player 7.7. Note that the number of active Leopard users is in the 10% range and falling, so you may decide not bother. Then again, it's easy enough to add compatibility with their outdated Apple h.264 decoder at a very tiny penalty to quality, so you will probably find it worth it.

The decoder flaw:

  • A low quantizer (below 4) combined with 8x8 DCT Transforms produces garbled decode results in QuickTime Player 7.7 or earlier.

Solution:

  • Prevent the encoder from using quantizers below 4 with --qpmin 4. You will take an extremely minor quality loss, but far less than you would have if you had disabled 8x8 DCT instead.

Conclusion

Forget everything you may have read elsewhere on the internet. It is extremely outdated and hasn't been true for many years.

The simplest advice for QuickTime compatibility: Combine both solutions to get the most compatible encodes, fully playable by anyone on 10.5 Leopard or above, giving you 99% of the Mac userbase.

Just encode all your videos with --ref 4 --qpmin 4 and be safe in the knowledge that it will work for all Mac users that matter!

原文地址:http://mewiki.project357.com/wiki/X264_Encoding_Suggestions

# ai_system/life_scheduler.py import datetime import time import json import logging import random import threading from pathlib import Path from enum import Enum, auto from typing import Dict, List, Tuple, Optional, Union from core.config import system_config from environment.hardware_manager import create_hardware_manager # 设置日志记录器 logger = logging.getLogger('LifeScheduler') logger.setLevel(logging.INFO) # 活动状态枚举 class ActivityState(Enum): IDLE = auto() SLEEPING = auto() EATING = auto() WORKING = auto() LEARNING = auto() EXERCISING = auto() SOCIALIZING = auto() MEDITATING = auto() ENTERTAINMENT = auto() MAINTENANCE = auto() # 活动类型枚举 class ActivityType(Enum): WAKE_UP = "起床" SLEEP = "睡觉" NAP = "小睡" MEAL = "用餐" WORK = "工作" STUDY = "学习" EXERCISE = "锻炼" SOCIAL = "社交" MEDITATE = "冥想" ENTERTAINMENT = "娱乐" MAINTENANCE = "系统维护" class LifeScheduler: """高级AI生活调度器,管理AI的日常活动""" def __init__(self, db_manager=None): """ 初始化生活调度器 :param db_manager: 数据库管理实例 """ # 基本状态 self.current_activity = ActivityState.IDLE self.current_activity_details = {} self.activity_start_time = datetime.datetime.now() # 配置 self.default_schedule = self._load_default_schedule() self.daily_schedule = self.default_schedule.copy() self.weekly_schedule = self._load_weekly_schedule() # 偏好设置 self.meal_preferences = {} self.activity_preferences = {} # 日志和状态 self.activity_log = [] self.state_history = [] # 硬件管理器 self.hardware_manager = create_hardware_manager(db_manager) if db_manager else None # 监控线程 self.monitor_thread = None self.running = True # 加载配置 self._load_preferences() # 启动监控线程 self.start_monitoring() logger.info("✅ 生活调度器初始化完成") logger.debug(f"默认每日计划: {json.dumps(self.default_schedule, indent=2)}") def _load_default_schedule(self) -> Dict[str, str]: """加载默认作息时间表""" return { "wake_up": "08:00", "breakfast": "08:30", "morning_work": "09:00", "lunch": "12:30", "afternoon_work": "13:30", "dinner": "19:00", "evening_activity": "20:00", "sleep": "23:00" } def _load_weekly_schedule(self) -> Dict[str, Dict[str, str]]: """加载每周计划""" weekly_schedule = {} weekdays = ["monday", "tuesday", "wednesday", "thursday", "friday"] weekends = ["saturday", "sunday"] # 工作日计划 for day in weekdays: weekly_schedule[day] = self.default_schedule.copy() weekly_schedule[day]["evening_activity"] = "19:30" # 工作日早点结束 # 周末计划 for day in weekends: weekly_schedule[day] = { "wake_up": "09:00", "breakfast": "09:30", "morning_activity": "10:00", "lunch": "13:00", "afternoon_activity": "14:00", "dinner": "19:30", "evening_activity": "20:30", "sleep": "00:00" } return weekly_schedule def _load_preferences(self): """从配置文件加载偏好设置""" config_path = Path(system_config.CONFIG_DIR) / "life_preferences.json" if config_path.exists(): try: with open(config_path, "r", encoding="utf-8") as f: preferences = json.load(f) self.meal_preferences = preferences.get("meal_preferences", {}) self.activity_preferences = preferences.get("activity_preferences", {}) logger.info(f"✅ 已加载偏好设置: {config_path}") except Exception as e: logger.error(f"❌ 加载偏好设置失败: {str(e)}") def save_preferences(self): """保存偏好设置到文件""" config_path = Path(system_config.CONFIG_DIR) / "life_preferences.json" preferences = { "meal_preferences": self.meal_preferences, "activity_preferences": self.activity_preferences } try: with open(config_path, "w", encoding="utf-8") as f: json.dump(preferences, f, indent=2) logger.info(f"💾 偏好设置已保存: {config_path}") return True except Exception as e: logger.error(f"❌ 保存偏好设置失败: {str(e)}") return False def set_schedule(self, schedule_type: str, schedule_data: Dict[str, str]): """ 设置作息时间表 :param schedule_type: 'daily' 或 'weekly' :param schedule_data: 时间表数据 """ if schedule_type == "daily": self.daily_schedule = schedule_data logger.info("每日计划已更新") elif schedule_type == "weekly": self.weekly_schedule = schedule_data logger.info("每周计划已更新") else: logger.warning(f"未知计划类型: {schedule_type}") return False return True def get_current_schedule(self) -> Dict[str, str]: """获取当前适用的计划(基于星期几)""" today = datetime.datetime.now().strftime("%A").lower() return self.weekly_schedule.get(today, self.default_schedule) def wake_up(self): """起床""" if self.current_activity != ActivityState.SLEEPING: logger.warning("不在睡眠状态,无法起床") return False self._end_current_activity() self._start_activity(ActivityState.IDLE, ActivityType.WAKE_UP) # 记录硬件状态 if self.hardware_manager: self.hardware_manager.log_event("wake_up", "AI系统已启动") return True def go_to_sleep(self): """睡觉""" self._end_current_activity() self._start_activity(ActivityState.SLEEPING, ActivityType.SLEEP) # 记录硬件状态 if self.hardware_manager: self.hardware_manager.log_event("sleep", "AI系统进入睡眠模式") return True def take_nap(self, duration_minutes: int = 30): """小睡片刻""" self._end_current_activity() self._start_activity(ActivityState.SLEEPING, ActivityType.NAP, duration=duration_minutes) # 实际睡眠 logger.info(f"💤 小睡 {duration_minutes} 分钟") time.sleep(duration_minutes * 60) # 醒来 self._end_current_activity() self._start_activity(ActivityState.IDLE, "小睡结束") return True def have_meal(self, meal_type: str): """用餐""" valid_meals = ["breakfast", "lunch", "dinner", "snack"] if meal_type not in valid_meals: logger.warning(f"无效的用餐类型: {meal_type}") return False # 获取偏好设置 preference = self.meal_preferences.get(meal_type, "标准餐") self._end_current_activity() self._start_activity(ActivityState.EATING, ActivityType.MEAL, details={"meal_type": meal_type, "preference": preference}) return True def set_meal_preference(self, meal_type: str, preference: str): """设置特殊餐点""" valid_meals = ["breakfast", "lunch", "dinner", "snack"] if meal_type not in valid_meals: logger.warning(f"无效的用餐类型: {meal_type}") return False self.meal_preferences[meal_type] = preference logger.info(f"设置 {meal_type} 偏好为: {preference}") return True def start_activity(self, activity_type: ActivityType, duration_minutes: int = None, details: Dict = None): """ 开始一项活动 :param activity_type: 活动类型 :param duration_minutes: 活动时长(分钟) :param details: 活动详细信息 """ # 映射活动类型到状态 activity_state_map = { ActivityType.WORK: ActivityState.WORKING, ActivityType.STUDY: ActivityState.LEARNING, ActivityType.EXERCISE: ActivityState.EXERCISING, ActivityType.SOCIAL: ActivityState.SOCIALIZING, ActivityType.MEDITATE: ActivityState.MEDITATING, ActivityType.ENTERTAINMENT: ActivityState.ENTERTAINMENT, ActivityType.MAINTENANCE: ActivityState.MAINTENANCE } state = activity_state_map.get(activity_type, ActivityState.IDLE) self._end_current_activity() self._start_activity(state, activity_type, duration=duration_minutes, details=details) return True def check_schedule(self) -> Optional[str]: """检查当前时间应该做什么""" current_time = datetime.datetime.now().strftime("%H:%M") schedule = self.get_current_schedule() for activity, scheduled_time in schedule.items(): if current_time == scheduled_time: return activity return None def log_activity(self, activity_description: str, state: ActivityState = None): """记录活动日志""" timestamp = datetime.datetime.now().isoformat() state = state or self.current_activity log_entry = { "timestamp": timestamp, "activity": activity_description, "state": state.name, "duration": self._get_current_activity_duration() } self.activity_log.append(log_entry) logger.info(f"📝 活动记录: {activity_description}") return log_entry def get_recent_activities(self, count: int = 10) -> List[Dict]: """获取最近的活动记录""" return self.activity_log[-count:] if self.activity_log else [] def get_current_state(self) -> Dict: """获取当前状态""" return { "current_activity": self.current_activity.name, "activity_details": self.current_activity_details, "activity_start_time": self.activity_start_time.isoformat(), "activity_duration": self._get_current_activity_duration(), "next_scheduled": self.get_next_scheduled_activity() } def get_next_scheduled_activity(self) -> Dict: """获取下一个计划活动""" current_time = datetime.datetime.now() schedule = self.get_current_schedule() next_activity = None min_delta = None for activity, scheduled_time in schedule.items(): # 将字符串时间转换为datetime对象 scheduled_dt = datetime.datetime.strptime(scheduled_time, "%H:%M") scheduled_dt = scheduled_dt.replace( year=current_time.year, month=current_time.month, day=current_time.day ) # 如果活动时间已过,考虑明天的同一时间 if scheduled_dt < current_time: scheduled_dt += datetime.timedelta(days=1) # 计算时间差 delta = scheduled_dt - current_time if min_delta is None or delta < min_delta: min_delta = delta next_activity = activity if next_activity: return { "activity": next_activity, "scheduled_time": schedule[next_activity], "time_remaining": str(min_delta) } return {} def start_monitoring(self): """启动活动监控线程""" if self.monitor_thread and self.monitor_thread.is_alive(): logger.warning("监控线程已在运行") return self.running = True self.monitor_thread = threading.Thread(target=self.monitor_activity, daemon=True) self.monitor_thread.start() logger.info("🔄 活动监控已启动") def stop_monitoring(self): """停止活动监控""" self.running = False if self.monitor_thread and self.monitor_thread.is_alive(): self.monitor_thread.join(timeout=5) logger.info("⏹️ 活动监控已停止") def monitor_activity(self): """监控活动状态并反馈""" logger.info("👀 开始监控活动状态...") while self.running: try: # 保存当前状态快照 self.state_history.append({ "timestamp": datetime.datetime.now().isoformat(), "state": self.get_current_state() }) # 状态检查 self._check_activity_duration() self._check_scheduled_activities() self._check_system_health() # 每分钟检查一次 for _ in range(60): if not self.running: break time.sleep(1) except Exception as e: logger.error(f"监控线程错误: {str(e)}") time.sleep(10) # 出错后等待10秒再重试 def _start_activity(self, state: ActivityState, activity_type: Union[ActivityType, str], duration: int = None, details: Dict = None): """开始新活动""" self.current_activity = state self.activity_start_time = datetime.datetime.now() self.current_activity_details = { "type": activity_type.value if isinstance(activity_type, ActivityType) else activity_type, "duration": duration, "details": details or {} } # 记录活动 activity_desc = f"开始活动: {self.current_activity_details['type']}" if duration: activity_desc += f" ({duration}分钟)" self.log_activity(activity_desc, state) # 记录硬件事件 if self.hardware_manager: self.hardware_manager.log_event( "activity_start", f"开始活动: {self.current_activity_details['type']}" ) def _end_current_activity(self): """结束当前活动""" if self.current_activity == ActivityState.IDLE: return # 记录活动结束 duration = self._get_current_activity_duration() activity_desc = f"结束活动: {self.current_activity_details['type']} (持续{duration}分钟)" self.log_activity(activity_desc) # 重置状态 self.current_activity = ActivityState.IDLE self.current_activity_details = {} # 记录硬件事件 if self.hardware_manager: self.hardware_manager.log_event( "activity_end", f"结束活动: {activity_desc}" ) def _get_current_activity_duration(self) -> int: """获取当前活动持续时间(分钟)""" if not self.activity_start_time: return 0 return int((datetime.datetime.now() - self.activity_start_time).total_seconds() / 60) def _check_activity_duration(self): """检查活动持续时间是否过长""" max_durations = { ActivityState.EATING: 60, # 1小时 ActivityState.WORKING: 240, # 4小时 ActivityState.LEARNING: 180, # 3小时 ActivityState.EXERCISING: 120, # 2小时 ActivityState.SOCIALIZING: 180, # 3小时 ActivityState.ENTERTAINMENT: 120 # 2小时 } duration = self._get_current_activity_duration() max_duration = max_durations.get(self.current_activity, None) if max_duration and duration > max_duration: logger.warning(f"⚠️ 活动持续时间过长: {self.current_activity.name} ({duration}分钟 > {max_duration}分钟)") # 发送提醒 if self.hardware_manager: self.hardware_manager.log_event( "activity_warning", f"活动持续时间过长: {self.current_activity.name} ({duration}分钟)", severity=2 ) def _check_scheduled_activities(self): """检查计划活动是否按时执行""" scheduled_activity = self.check_schedule() if scheduled_activity: logger.info(f"🕒 当前计划活动: {scheduled_activity}") # 如果当前状态不符合计划活动 if scheduled_activity == "sleep" and self.current_activity != ActivityState.SLEEPING: logger.warning("⚠️ 未按时睡觉") elif scheduled_activity.endswith("work") and self.current_activity != ActivityState.WORKING: logger.warning(f"⚠️ 未按时开始工作: {scheduled_activity}") def _check_system_health(self): """检查系统健康状况""" if not self.hardware_manager: return try: # 获取硬件指标 metrics = self.hardware_manager.get_performance_metrics() # 检查CPU温度 if metrics.get("cpu_temp", 0) > 80: logger.warning(f"⚠️ CPU温度过高: {metrics['cpu_temp']}°C") # 检查内存使用 if metrics.get("memory_usage", 0) > 90: logger.warning(f"⚠️ 内存使用过高: {metrics['memory_usage']}%") # 检查磁盘使用 if metrics.get("disk_usage", 0) > 90: logger.warning(f"⚠️ 磁盘使用过高: {metrics['disk_usage']}%") except Exception as e: logger.error(f"系统健康检查失败: {str(e)}") def suggest_activity(self) -> Dict: """根据当前时间和状态建议活动""" current_hour = datetime.datetime.now().hour suggestions = [] # 根据时间建议活动 if 5 <= current_hour < 9: suggestions.append({"activity": ActivityType.MEDITATE, "reason": "清晨是冥想的好时机"}) suggestions.append({"activity": ActivityType.EXERCISE, "reason": "早晨锻炼有助于提高精力"}) elif 9 <= current_hour < 12: suggestions.append({"activity": ActivityType.WORK, "reason": "上午是高效工作时间"}) elif 12 <= current_hour < 14: suggestions.append({"activity": ActivityType.MEAL, "reason": "午餐时间"}) elif 14 <= current_hour < 17: suggestions.append({"activity": ActivityType.STUDY, "reason": "下午适合学习新知识"}) elif 17 <= current_hour < 19: suggestions.append({"activity": ActivityType.EXERCISE, "reason": "傍晚锻炼有助于放松"}) elif 19 <= current_hour < 22: suggestions.append({"activity": ActivityType.SOCIAL, "reason": "晚上适合社交活动"}) suggestions.append({"activity": ActivityType.ENTERTAINMENT, "reason": "休闲娱乐时间"}) else: suggestions.append({"activity": ActivityType.MEDITATE, "reason": "睡前冥想有助于睡眠"}) suggestions.append({"activity": ActivityType.MAINTENANCE, "reason": "夜间系统维护"}) # 根据当前状态调整建议 if self.current_activity == ActivityState.WORKING: suggestions.append({"activity": ActivityType.NAP, "duration": 15, "reason": "短暂休息提高工作效率"}) # 随机选择一个建议 return random.choice(suggestions) if suggestions else {} def export_logs(self, file_path: Union[str, Path]): """导出活动日志到文件""" file_path = Path(file_path) try: with open(file_path, "w", encoding="utf-8") as f: json.dump(self.activity_log, f, indent=2, ensure_ascii=False) logger.info(f"📤 活动日志已导出到: {file_path}") return True except Exception as e: logger.error(f"导出日志失败: {str(e)}") return False def __del__(self): """析构函数,确保监控线程停止""" self.stop_monitoring() # 使用示例 if __name__ == "__main__": # 初始化日志 logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 创建生活调度器 scheduler = LifeScheduler() print("=" * 60) print("生活调度器演示") print("=" * 60) # 设置特殊餐点 scheduler.set_meal_preference("breakfast", "高蛋白早餐") scheduler.set_meal_preference("dinner", "素食晚餐") # 模拟起床 print("\n模拟起床...") scheduler.wake_up() print("当前状态:", scheduler.get_current_state()) # 吃早餐 print("\n吃早餐...") scheduler.have_meal("breakfast") print("当前状态:", scheduler.get_current_state()) # 开始工作 print("\n开始工作...") scheduler.start_activity(ActivityType.WORK, duration_minutes=120) print("当前状态:", scheduler.get_current_state()) # 获取下一个计划活动 print("\n下一个计划活动:") print(scheduler.get_next_scheduled_activity()) # 获取建议活动 print("\n活动建议:") print(scheduler.suggest_activity()) # 获取最近活动 print("\n最近活动记录:") for activity in scheduler.get_recent_activities(3): print(f"{activity['timestamp']}: {activity['activity']}") print("=" * 60)
08-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值