前几天实现了在 nginx 中使用 lua 实现远程鉴权,今天想试试在 IIS 中能不能实现相同的功能。查询资料发现需要使用 URL 重写和 HTTP 请求模块,没有深究。干脆使用 ASP.NET 中间件来实现吧。
在 StratUp.cs 的 Configure 方法中,或 Program.cs 文件中添加以下代码:
// 远程鉴权
app.Use(async (context, next) =>
{
var ip = context.Connection.RemoteIpAddress!.ToString();
var ua = context.Request.Headers.UserAgent.ToString();
var host = context.Request.Host.Host;
var uri = new Uri(context.Request.GetDisplayUrl()).PathAndQuery;
var client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(1); // 设置超时时间
try
{
var requestUrl = "https://鉴权地址/";
var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUrl);
requestMessage.Headers.Add("X-Real-IP", ip);
requestMessage.Headers.Add("User-Agent", ua);
requestMessage.Headers.Add("X-Forwarded-Host", host);
requestMessage.Headers.Add("X-Forwarded-Uri", uri);
// 发送请求
var response = await client.SendAsync(requestMessage);
// 检查响应状态码
if (response.StatusCode == HttpStatusCode.Forbidden)
{
// 如果返回403,则拒绝访问
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
await context.Response.WriteAsync("Access Denied");
}
else
{
// 如果返回其他状态码,则继续执行管道中的下一个中间件
await next();
}
}
catch (TaskCanceledException ex) when (ex.CancellationToken.IsCancellationRequested)
{
// 如果请求超时(任务被取消),则继续执行管道中的下一个中间件
await next();
}
catch
{
// 如果遇到错误,则继续执行管道中的下一个中间件
await next();
}
});
代码很简单,使用 HttpClient 发送请求,若返回 403 则拒绝访问,其它情况继续执行业务逻辑,超时或报错的情况按需修改即可。
若鉴权接口在私网中,建议将鉴权接口域名和私网 IP 添加到 hosts 文件中。
在 access_by_lua_block 代码块中实现远程鉴权:
#鉴权-START resolver 223.5.5.5; # 使用公共 DNS access_by_lua_block { local http = require("resty.http") local httpc = http.new() httpc:set_timeout(500) -- 连接超时 local res, err = httpc:request_uri("https://鉴权地址/", { method = "GET", headers = { ["X-Real-IP"] = ngx.var.remote_addr, ["User-Agent"] = ngx.var.http_user_agent, ["X-Forwarded-Host"] = ngx.var.host, ["X-Forwarded-Uri"] = ngx.var.request_uri, }, ssl_verify = false, -- 禁用 SSL 验证 timeout = 500, -- 读取超时 }) if not res then ngx.log(ngx.ERR, "Failed to request: " .. err) end if res and res.status == 403 then ngx.exit(ngx.HTTP_FORBIDDEN) -- return ngx.redirect("https://一个显示403友好信息的页面.html") end } #鉴权-END
注意更改接口地址和友情显示 403 页面地址。
本示例仅捕获 403 状态码,500、408 等其它异常情况视为允许访问,请根据业务需求自行添加状态码的判断。
若超时也会进入
if not res then
代码块。建议将此代码部署在 nginx 主配置文件的 http 代码块中(宝塔面板中的路径:/www/server/nginx/nginx/conf/nginx.conf),如果你只想为单个网站鉴权,也可以放在网站配置文件的 server 块中。
若鉴权接口在私网中,建议将鉴权接口域名和私网 IP 添加到 hosts 文件中。
附
直接输出字符串
ngx.header.content_type = "text/plain"; ngx.say("hello world!")
输出到日志
ngx.log(ngx.ERR, "Response status: " .. res.status)
日志在网站的 站名.error.log 中查看。
宝塔面板查看方式:日志 - 网站日志 - 异常
若想获取服务器 CPU 使用率等信息并传递给远程鉴权接口,请参考此文。
常见问题
no resolver defined to resolve
原因:没有定义 DNS 解析器
解决方法:在 http 块或 server 块中添加
resolver 8.8.8.8 valid=30s;
,当然使用接入商自己的公共 DNS 可能更合适。unable to get local issuer certificate
原因:没有配置 SSL 证书信息
解决方法:添加 request_uri 参数:
ssl_verify = true, -- 启用 SSL 验证 ssl_trusted_certificate = "证书路径", -- 指定 CA 证书路径
或
ssl_verify = false, -- 禁用 SSL 验证
若您不想用 lua,可以用 nginx 原生自带的 auth_request 模块来实现。
鉴权方式有许多,譬如可以用 lua 的 access_by_lua 来实现,这里用 nginx 自带的 auth_request,虽然功能简单,但效率更高。
第一步,确保 nginx 已编译安装 auth_request 模块,见此文。
第二步,打开需要鉴权的网站的 nginx 配置文件,添加以下代码块:
#鉴权-START
location / {
auth_request /auth;
error_page 403 = @error403;
#PHP-INFO-START PHP引用配置,可以注释或修改
include enable-php-**.conf;
#PHP-INFO-END
}
location = /auth {
internal;
proxy_pass https://鉴权地址;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_intercept_errors on;
#proxy_read_timeout 1s; # 超时会报 500
}
location @error403 {
#default_type text/plain;
#return 403 'forbidden';
return 302 https://一个显示403友好信息的页面.html;
}
#鉴权-END
一般放在所有的 location 之前。
这里自定义请求头 X-Forwarded-Host
与 X-Forwarded-Uri
用来传递 host 与 uri。API 应从 Header 中相应取值。
宝塔面板中是通过 include enable-php-**.conf;
的方式调用 PHP ,那么可以将此行移入上面的 location /
代码块中,因为此代码块能匹配所有的请求路径。
最后,若鉴权接口在私网中,将鉴权接口域名和私网 IP 添加到 hosts 文件中。
实例化方法一:DbSearcher(String dbFile, QueryType queryType, String key)
实例化方法二:DbSearcher(InputStream is, QueryType queryType, String key)
方法一通过传入文件路径来实例化,方法二通过传入文件流来实例化;
当 queryType 为 MEMORY 时,方法一和方法二只有在实例化时有性能差别,差别在于将指定路径的文件读到内存中保存;在执行 Search 方法时无性能差别,因为都是在内存中执行查找;
queryType 为 MEMORY 和 BTREE 的差别在于前者是在内存中查找,速度快但占内存,后者是在文件中查找,速度慢但省内存。
错误:Padding is invalid and cannot be removed.
原因:可能是数据库文件与密钥不一致。
今天忘了带鼠标,正巧笔记本电脑的触摸板驱动坏了,一时也用不了,所以想到用 iPhone 当作电脑的触控板来用。电脑操作系统是 Windows。
一、电脑上下载并安装 Remote Helper(此步需要会使用纯键盘来操作电脑,常用的键是 TAB、方向键、回车键)
二、手机上 App Store 中搜索并获取 鼠标·键盘
电脑和手机需要连接同一局域网,如果没有局域网,可以将电脑连接 iPhone 的热点。
打开 App,搜索 PC,授权,就可以控制光标了。
如果电脑未显示光标,尝试双击 CTRL 键来确定当前光标的位置,前提是安装了 PowerToys。
推荐使用 SignalR 来平替 WebSocket,参考教程。
【服务端(.NET)】
一、创建 WebSocketHandler 类,用于处理客户端发送过来的消息,并分发到其它客户端
public class WebSocketHandler
{
private static List<WebSocket> connectedClients = [];
public static async Task Handle(WebSocket webSocket)
{
connectedClients.Add(webSocket);
byte[] buffer = new byte[1024];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
Console.WriteLine($"Received message: {message}");
// 处理接收到的消息,例如广播给其他客户端
await BroadcastMessage(message, webSocket);
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
connectedClients.Remove(webSocket);
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
private static async Task BroadcastMessage(string message, WebSocket sender)
{
foreach (var client in connectedClients)
{
if (client != sender && client.State == WebSocketState.Open)
{
await client.SendAsync(Encoding.UTF8.GetBytes(message), WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
}
二、在 Program.cs 或 Startup.cs 中插入:
// 添加 WebSocket 路由
app.UseWebSockets();
app.Use(async (context, next) =>
{
if (context.Request.Path == "/chat")
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await WebSocketHandler.Handle(webSocket);
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});
这里的路由路径可以更改,此处将会创建一个 WebSocket 连接,并将其传递给 WebSocketHandler.Handle 方法进行处理。
也可以用控制器来接收 WebSocket 消息。
【客户端(JS)】
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<title>WebSocket 示例(JS + ASP.NET)</title>
<style>
#list { width: 100%; max-width: 500px; }
.tip { color: red; }
</style>
</head>
<body>
<h2>WebSocket 示例(JS + ASP.NET)</h2>
<textarea id="list" readonly rows="20"></textarea>
<div>
<input type="text" id="msg" />
<button onclick="fn_send()">发送</button>
<button onclick="fn_disconnect()">断开</button>
</div>
<p id="tip_required">请输入要发送的内容</p>
<p id="tip_closed">WebSocket 连接未建立</p>
<script>
var wsUrl = "wss://" + window.location.hostname + ":" + window.location.port + "/chat";
var webSocket;
var domList = document.getElementById('list');
// 初始化 WebSocket 并连接
function fn_ConnectWebSocket() {
webSocket = new WebSocket(wsUrl);
// 向服务端发送连接请求
webSocket.onopen = function (event) {
var content = domList.value;
content += "[ WebSocket 连接已建立 ]" + '\r\n';
domList.innerHTML = content;
document.getElementById('tip_closed').style.display = 'none';
webSocket.send(JSON.stringify({
msg: 'Hello'
}));
};
// 接收服务端发送的消息
webSocket.onmessage = function (event) {
if (event.data) {
var content = domList.value;
content += event.data + '\r\n';
domList.innerHTML = content;
domList.scrollTop = domList.scrollHeight;
}
};
// 各种情况导致的连接关闭或失败
webSocket.onclose = function (event) {
var content = domList.value;
content += "[ WebSocket 连接已关闭,3 秒后自动重连 ]" + '\r\n';
domList.innerHTML = content;
document.getElementById('tip_closed').style.display = 'block';
setTimeout(function () {
var content = domList.value;
content += "[ 正在重连... ]" + '\r\n';
domList.innerHTML = content;
fn_ConnectWebSocket();
}, 3000); // 3 秒后重连
};
}
// 检查连接状态
function fn_IsWebSocketConnected() {
if (webSocket.readyState === WebSocket.OPEN) {
document.getElementById('tip_closed').style.display = 'none';
return true;
} else {
document.getElementById('tip_closed').style.display = 'block';
return false;
}
}
// 发送内容
function fn_send() {
if (fn_IsWebSocketConnected()) {
var message = document.getElementById('msg').value;
document.getElementById('tip_required').style.display = message ? 'none' : 'block';
if (message) {
webSocket.send(JSON.stringify({
msg: message
}));
}
}
}
// 断开连接
function fn_disconnect() {
if (fn_IsWebSocketConnected()) {
// 部分浏览器调用 close() 方法关闭 WebSocket 时不支持传参
// webSocket.close(001, "Reason");
webSocket.close();
}
}
// 执行连接
fn_ConnectWebSocket();
</script>
</body>
</html>
【在线示例】
https://xoyozo.net/Demo/JsNetWebSocket
【其它】
-
服务端以 IIS 作为 Web 服务器,那么需要安装 WebSocket 协议
-
一个连接对应一个客户端(即 JS 中的 WebSocket 对象),注意与会话 Session 的区别
-
在实际项目中使用应考虑兼容性问题
-
程序设计应避免 XSS、CSRF 等安全隐患
-
参考文档:https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/websockets
如果手机开启了自动横屏,那么网页就会跟着旋转,导致网页宽度变大,高度变小,页面布局不友好,我们可以通过判断屏幕方向 api,用 css 设置旋转。
HTML:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<title>保持竖屏示例</title>
</head>
<body>
<div id="app">
<div class="page">
<div>把手机横过来试试</div>
<div>页面永远保持竖屏方向</div>
</div>
</div>
</body>
</html>
CSS:
body { margin: 0; }
.page { text-align: center; padding-top: 100px; }
@media screen and (orientation: landscape) {
body { width: 100vh; height: 100vw; overflow: hidden; }
.page.landscape-primary { transform: rotate(-90deg); transform-origin: top left; width: 100vh; height: 100vw; position: absolute; top: 100%; left: 0; }
.page.landscape-secondary { transform: rotate(90deg); transform-origin: top left; width: 100vh; height: 100vw; position: absolute; top: 0; left: 100%; }
}
JS:
function fn_set_orientation() {
var orientation = window.screen.orientation || window.screen.mozOrientation || window.screen.msOrientation;
const div = document.querySelector('.page');
console.log(orientation.type)
switch (orientation.type) {
case 'landscape-primary': {
div.classList.remove('landscape-secondary');
div.classList.add('landscape-primary');
break;
}
case 'landscape-secondary': {
div.classList.remove('landscape-primary');
div.classList.add('landscape-secondary');
break;
}
default: {
div.classList.remove('landscape-primary');
div.classList.remove('landscape-secondary');
break;
}
}
}
window.addEventListener("orientationchange", function () {
fn_set_orientation();
});
fn_set_orientation();
示例:
https://xoyozo.net/Demo/Orientation
可能的原因是 IIS 安装了“WebDAV 发布”,在 IIS - 模块 中可见 WebDAVModule
解决方法:在网站的 web.config 中设置:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
</system.webServer>
或在 IIS 中,在该网站的模块中删除 WebDAVModule。
如果网站需要用到 WebDAV 模块,那么考虑使用 Fetch API 或 XMLHttpRequest 来发送请求。
本文将详细介绍 stable diffusion webui 的下载、安装及问题解决。
Stable Diffusion 是 2022 年发布的深度学习文本到图像生成模型。它主要用于根据文本的描述产生详细图像,尽管它也可以应用于其他任务,如内补绘制、外补绘制,以及在提示词(英语)指导下产生图生图的翻译。它是一种潜在扩散模型,由慕尼黑大学的 CompVis 研究团体开发的各种生成性人工神经网络。它是由初创公司 StabilityAI,CompVis 与 Runway 合作开发的,并得到 EleutherAI 和 LAION 的支持。
其它问题请参考:
运行使用时问题《Windows 使用 Stable Diffusion 时遇到的各种问题整理》;
模型运用及参数《Stable Diffusion 个人推荐的各种模型及设置参数、扩展应用等合集》;
提示词生图咒语《Stable Diffusion 提示词词缀使用指南(Prompt)》;
不同类的模型Models说明《解析不同种类的 Stable Diffusion 模型 Models》;
绘制人物动作及手脚细节《Stable Diffusion 准确绘制人物动作及手脚细节(需 ControlNet 扩展)》;
各种风格对比及实际运用《AI绘图风格对照表/画风样稿详细研究记录及经验总结》;
一、环境准备
(一)硬件方面:
1. 显存
4G 起步,4G 显存支持生成 512*512 大小图片,超过这个大小将卡爆失败。
2. 硬盘
10G 起步,模型基本都在 5G 以上,有个 30G 硬盘不为过吧?现在硬盘容量应该不是个问题。
(二)软件方面:
1. Git
https://git-scm.com/download/win
下载最新版即可,对版本没有要求。
2. Python
https://www.python.org/downloads/
截止发稿(2023.3.6)时,最高版本只能用 3.10.*
,用 3.11.*
会出问题。
3. Nvidia CUDA
https://developer.download.nvidia.cn/compute/cuda/11.7.1/local_installers/cuda_11.7.1_516.94_windows.exe
版本 11.7.1,搭配 Nvidia 驱动 516.94,可使用最新版。
4. stable-diffusion-webui
https://github.com/AUTOMATIC1111/stable-diffusion-webui
核心部件当然用最新版本~~但注意上面三个的版本的兼容性。
5. 中文语言包
https://github.com/VinsonLaro/stable-diffusion-webui-chinese
下载 chinese-all-0306.json
和 chinese-english-0306.json
文件
6. 扩展(可选)
https://github.com/Mikubill/sd-webui-controlnet
下载整个 sd-webui-controlnet
压缩包
https://huggingface.co/Hetaneko/Controlnet-models/tree/main/controlnet_safetensors
https://huggingface.co/lllyasviel/ControlNet/tree/main/models
https://huggingface.co/TencentARC/T2I-Adapter/tree/main
试用时先下载第一个链接中的 control_openpose.safetensors
或 第二个链接中的 control_sd15_openpose.pth
文件
7. 模型
https://huggingface.co/models
https://civitai.com
可以网上去找推荐的一些模型,一般后缀名为 ckpt
、pt
、pth
、safetensors
,有时也会附带 VAE(.vae.pt
)或配置文件(.yaml
)。
类型 | 文件格式 | 存放目录 | 备注 |
---|---|---|---|
check point | .ckpt,.safetensors | \models\Stable-diffusion | 文件较大 |
vae | 名字带有 vae 的 | \models\vae | 细节更好地恢复,特别是眼睛和文字 |
Textual Inversion | *.pt | \embeddings | 一般文件很小,额外的 tag |
Lora | *.pt | \models\Lora | 调整模型,理解为风格化也可以 |
Hypernetworks | .pt,.ckpt,*.safetensors | \models\hypernetworks | 和 lora 工作方式相似,算法不同 |
这里可以学习一下模型的基本概念《解析不同种类的 Stable Diffusion 模型 Models,再也不用担心该用什么了》
二、安装流程
1. 安装 Git
就正常安装,无问题。
2. 安装 Python
建议安装在非 program files
、非 C 盘
目录,以防出现目录权限问题。
注意安装时勾选 Add Python to PATH
,这样可以在安装时自动加入 windows 环境变量 PATH 所需的 Python 路径。
3. 安装 Nvidia CUDA
正常安装,无问题。
4. 安装 stable-diffusion-webui
国内需要用到代理和镜像,请按照下面的步骤操作:
a) 编辑根目录下 launch.py
文件
将 https://github.com
替换为 https://ghproxy.com/https://github.com
,即使用 Ghproxy 代理,加速国内 Git。
如图将代码中所有类似地址都改掉(注意:不仅仅是图中所展示的这些)。
b) 执行根目录下 webui.bat
文件
根目录下将生成 tmp
和 venv
目录。
c) 编辑 venv
目录下 pyvenv.cfg
文件
将 include-system-site-packages = false
改为 include-system-site-packages = true
。
d) 配置 python 库管理器 pip
方便起见,在 \venv\Scripts
下打开 cmd
后执行如下命令:
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ # 镜像
pip freeze > requirements_versions.txt # 创建文件
pip install -r requirements_versions.txt # 执行此条命令前,请检查你的剩余磁盘空间
pip install xformer # 如果不执行此条命令,启动 Stable Diffusion 时可能会出现错误。xformer 还可以在后续使用中降低显卡占用。
xformer
会安装到 \venv\Lib\site-packages
中,安装失败可以用 pip install -U xformers
命试试。
e) 安装语言包
将文件 chinese-all-0306.json
和 chinese-english-0306.json
放到目录 \localizations
目录中。
运行 webui
后进行配置,操作方法见下。
f) 安装扩展(可选)
将 sd-webui-controlnet
解压缩到 \extensions
目录中。
将 control_sd15_openpose.pth
文件复制到 /extensions/sd-webui-controlnet/models
目录中。
不同的扩展可能还需要安装对应的系统,比如 controlnet
要正常使用则还需要安装 ffmpeg
等。
g) 安装模型
下载的各种模型放在 \models\Stable-diffusion
目录中即可。
h) 再次执行根目录下 webui.bat
文件
用浏览器打开 webui.bat
所提供的网址即可运行。
其中提供了网址:http://127.0.0.1:7860
。
打开该网址后在 Settings
-> User interface
-> Localization (requires restart)
设置语言,在菜单中选择 chinese-all-0220
(前提是已经在目录中放入了对应语言包,见上),点击 Apply Settings
确定,并且点击 Reload UI
重启界面后即可。
好了,现在可以开始使用了~~
三、问题及注意点
1. python 版本错误
错误:
ERROR: Could not find a version that satisfies the requirement torch==1.13.1+cu117
ERROR: No matching distribution found for torch==1.13.1+cu117
这是由于 python 版本不对导致的(上面提过了,截止发稿时不能追求新版本),要用 python 3.10.*
版本。
解决来源:https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/7166
2. pip版本错误
警告:
[notice] A new release of pip available: 22.3.1 -> 23.0.1
[notice] To update, run: D:\stable-diffusion-webui\venv\Scripts\python.exe -m pip install --upgrade pip
提示中已经给出了解决方案:
在 \venv\Scripts\
目录中打开 cmd
,执行
python.exe -m pip install --upgrade pip
3. 安装或执行停滞
如果在执行 webui.bat
进行包下载安装时或者生成图片时会卡很久都没反应,那么这时可以复制包名,进入 python 安装目录
或 \venv\Scripts\
目录中打开 cmd
,执行
pip install 包名
也可以通过任务管理查看网络状态,如果网络在玩命下载,那么就等着吧~~
4. xFormers 安装不上
很多同学都反应 xformers 无法安装,可以用以下的方法试试:
检查 Dreambooth 要求的 Python 版本:
如果您的 Python 版本低于 3.6,请安装最新的 Python 版本,并重复尝试安装 xformers。
# 据此可以在终端中运行以下命令,以检查您的 Python 版本:
python --version
安装依赖项:xformers 有许多依赖项,如果这些依赖项没有正确安装可能会导致升级失败。您可以尝试安装以下依赖项:
pip install numpy scipy torch torchaudio transformers
清除 pip 缓存并重新安装:
# 清除 xformers 缓存:运行以下命令清除 xformers 缓存。
pip uninstall -y xformers
pip cache purge
# 更新 pip:确保您正在使用最新版本的 pip,可以运行以下命令更新 pip。
pip install --upgrade pip
# 安装 xformers:在清除了缓存并更新了 pip 之后,重新安装 xformers。
pip install xformers
手动安装 xformers 指定版本
如果上述步骤仍然无法解决问题,可尝试手动安装 Dreambooth 所需的 xformers 版本。在 Dreambooth 的文档中,可以找到 xformers 的版本要求。
pip install xformers==0.0.17.dev465
使用 conda 环境
如果您使用的是 conda 环境,请尝试在 conda 环境中安装 xformers。
# 创建 conda 环境
conda create --name myenv
# 激活 conda 环境并安装 xformers
conda activate myenv
pip install xformers
网络问题
如果已经配置好了代理,就不要考虑这个了。
检查网络连接:请确保您的计算机与互联网连接,并且网络连接没有被防火墙或代理服务器阻止:
# 检查网络连接是否正常
ping google.com
非必要
你确定需要使用 xformers 么?如果不需要,可以在webui-user.bat
中把--xformers
去掉试试。其它
如果上述方法还是无法解决问题,请尝试在 OpenAI 的论坛或者 Dreambooth 的 GitHub 页面上寻求更多帮助。-_-!
5. 其他安装问题
删除 /tmp
和 /venv
目录后重启 webui.bat
试试。
6. 硬件问题
一般显卡不达标,就会爆卡,解决办法就是编辑根目录下 webui-user.bat
文件,试一下修改参数 COMMANDLINE_ARGS
即可。
以下几个设置逐一测试看看哪个适合自己。
set COMMANDLINE_ARGS=--lowvram --precision full --no-half --skip-torch-cuda-test
set COMMANDLINE_ARGS=--lowvram --precision full --no-half
set COMMANDLINE_ARGS=--lowvram
本机显存 4G,使用最后一个配置方法,可以烧出 2048*1080 的图,前两种方法反而会在最后爆卡。
最后,预祝各位成功~~
dog drink~~ where is dog?
参考:
【AI 繪畫】Stable-Diffusion 通過骨架分析插件 ControlNet 來製作超有意境的圖片
Stable Diffusion 2.1 + WebUI 的安装与使用(极详细)
低配显卡想玩 Stable Diffusion?修改一个配置就行
整合包
原生判断
window.addEventListener('scroll', scroll)
function scroll() {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
if (scrollTop === 0) {
console.log('滚动到顶了');
}
if (scrollTop + clientHeight >= scrollHeight - 100) {
console.log('滚动到底了');
}
}
window.removeEventListener('scroll', scroll) // 移除滚动事件
scrollTop:文档在可视区上沿的位置距离文档顶部的距离
clientHeight:可视区的高度
scrollHeight:文档总高度
100:用于在滚动到底部之前提前加载内容(如瀑布流),提高用户体验,请自行修改数值(建议不小于 2 像素,以规避在部分浏览器上因获得值为小数时可能无法触发的问题)
jQuery 判断
window.addEventListener('scroll', scroll)
function scroll() {
const doc_height = $(document).height();
const scroll_top = $(document).scrollTop();
const window_height = $(window).height();
if (scroll_top === 0) {
console.log('滚动到顶了');
} else if (scroll_top + window_height >= doc_height - 100) {
console.log('滚动到底了');
}
}