Deprecated: Creation of dynamic property Typecho\Widget\Request::$feed is deprecated in E:\CloudMusic\VSCode\Home\Apache24\htdocs\var\Widget\Archive.php on line 246
dhui's Blog - 默认分类 https://dhui626.github.io/index.php/category/default/ 只是一个默认分类 基于 OpenGL 的 Minecraft 世界渲染器 https://dhui626.github.io/index.php/archives/73/ 2024-11-19T15:32:00+00:00 Minecraft Mini Renderer本页面用于项目《基于 OpenGL 的 Minecraft 世界渲染器》展示。渲染器基于 C++ 与 OpenGL,由本人独立完成。(2024.9~至今)截至目前的最终渲染结果如下Final下面按时间顺序来展示各阶段进行的工作与结果。OpenGL 基础功能一切的开始!起初这只是一个 OpenGL 学习项目(直到现在项目目录都是LearnOpenGL)Basic Renderer用 OpenGL 渲染一个草方块,并编写 shader 应用 Blinn-Phong 光照模型。后面发现了很多问题并修正:纹理图案在边界处异常,原因是下载的纹理图案有模糊处理,替换成原图后正常。当时实现的实际是 Phong 光照模型,specular 分量的计算未用到半程向量,后修正(顺便一提,GAMES202 的作业框架也存在此错误,且作业1中 specular 颜色值传入了 0,实际计算出的 specular 分量为 0,可能就因此没被助教们发现?)Chunk Render Test实现基于 Perlin 噪声的区块生成器,并启用 ImGui 进行调试。场景中只有单个区块(32×32)。至此性能问题就被充分暴露了:由于我每个方块都调用了一次draw call,因此上面的简单场景也只有10hz,如果场景中有多个区块将是个灾难。性能优化主要的优化步骤总结为如下三步:每个区块类内维护一个 VAO,在渲染该区块时只执行一次draw call只对接触到空气的面加入到 vertices 和 indices 数组,实际很多面不需要绘制(藏在泥土中的,以及两个相邻方块的接触面)。启用背面剔除在解决了以上问题后,可以生成多个区块了,并加入了 GAMES202 中介绍的阴影算法(shadow map, PCF, PCSS)Shadow Algorithms在图下方的方块边缘处阴影缺了一块,这与修复 Shadow Acne 设置的 bias 有关。Add Grass and Flowers修正世界生成逻辑,改用 Simplex 噪声,并添加了花草,结果如上图。考虑到花草和方块的渲染逻辑不同,后续也会使用不同的 shader ,本人将代码进行了重构。重构后一个区块可拥有多个 VAOs,且花草、方块以及后面加入的水面可以用不同的 shader 来渲染。Add Water加入水方块,并对水流使用不同的渲染逻辑(透明物体最后渲染),并在 vertex shader 中模拟水的流动(Gerstner waves)后处理后处理主要在屏幕空间完成,即利用 FBO 的渲染结果以及深度进行图像处理。Screen Space Fog水上雾化效果和水中漫游效果(Screen Space Fog),利用 FBO 的深度值来计算混合颜色。Stage3-2Bloom效果展示,利用 Gaussion Blur 对一张高亮图模糊化,并加到原图上。除此之外,还加入了以下调节:亮度、对比度、饱和度、锐度(已移除)、Gamma校正等Tone MappingTone Mapping,实现并比较了各种方法的结果,个人比较喜欢 CE 和 Filmic 。总结以上就是本人的 Minecraft Mini Renderer 的暂时进展。后续会加入更多内容,如 Cascade Shadow Map,MSAA,玩家模型等,本页面也将持续更新。GitHub 链接:https://github.com/dhui626/LearnOpenGLCommit History Blender 学习记录 https://dhui626.github.io/index.php/archives/71/ 2024-06-24T14:50:00+00:00 填坑,使用 Blender4.0 官网下载链接,参考Blender Guru 的教程文章主图是最终渲染图片。快捷方式鼠标滚轮按下: 调整视角Shift + 鼠标滚轮按下: 移动视角Shift + A: 添加物体G (grab): 移动物体G + X/Y/Z: 沿坐标轴X/Y/Z移动物体G + 鼠标滚轮按下: 沿某一坐标轴移动物体0: 摄像机视角N: 选项(常用于关掉那个窗口)S (scale) + X/Y/Z: 缩放物体R (rotate) + X/Y/Z: 旋转物体形状编辑网格细分:添加修改器 - 生成 - 表面细分 - 调节Catmull-Clark细分的层数编辑网格细节:选中物体 - 左上角物体模式 - 编辑模式 (快捷键Tab)衰减编辑:同时改变一系列点。滚轮控制点的范围(P2P变形的参数)切换透视模式:选框操作时可以选择物体背后的点解决网格重叠的渲染问题:修改器 - 生成 - 实体化 - 调节偏移量固定网格的部分点并隐藏:alt + 鼠标点击: 选中 ctrl + : 扩大范围 H: 隐藏添加新顶点:选中部分点,E + 鼠标拖动让网格顶点落在另一个网格上,而不重叠:修改器 - 形变 - 缩裹,并指定特定的目标雕刻模式:左上角切换,常用:膨胀(I) 抓起(G)遮罩(Mask):快捷键 M,选定不进行雕刻的区域。Ctrl + I:反选。遮罩 - 平滑遮罩:将Mask平滑化。绑定两个物体:先选子对象(跟着父对象移动的),再选父对象,快捷键 Ctrl + P - 物体(保持变换)选中面 - Ctrl+B:斜面工具,常用于将尖锐的边光滑化,在编辑时操作滚轮控制层数。选中顶点 - Ctrl+R:在网格中建立细分修改器 - 形变 - 简易形变:将网格进行拉伸、缩小去除网格重复点:A(全选) + M(Merge) - 按距离移动物体时吸附:G + B,点击对应的点,过程中使用 Alt + 滚轮 调整视角重新计算法线:选中面 - Shift+N - 勾选向内材质与渲染材质 - 添加材质 - 修改颜色、糙度等等。材质下载:Poliigon,网站有 add-on 安装教程。Texture Paint:进行网格纹理的绘制,局部视图:快捷键 / 几何节点(Geometry Nodes):对网格进行自定义修改,过于复杂。视频视图 - 裁剪起始:相机靠近物体太近时会穿过物体,调为最小(0.001m)可解决。Fly模式:Shift+`,第一人称视角观察,WASD移动/QE上升下降等更改物体不同部位的材质:建立多个材质环境光添加:World - 颜色 - 天空纹理亮度调节:Scene - 胶片 - 曝光度 (也可在环境光设置中调节)滤镜添加:渲染 - 色彩管理 - 胶片效果()后处理:Compositing - 勾选“使用节点” - 添加节点(色彩平衡, etc)开始渲染:渲染 - 渲染动画(Ctrl + F12)景深设置:选中相机 - 勾选景深,并调节光圈级数动画I (insert): 添加关键帧曲线编辑:Animation - 曲线编辑器 - 编辑Bezier曲线曲线尺度的调整:HOME键 / Ctrl + 按下鼠标滚轮输出格式调整:输出 - 文件格式 - PNG(不建议直接生成视频,如果渲染中计算机意外重启可能丢失所有进度)视频生成文件 - 新建 - 视频编辑(或在当前项目中添加“视频编辑”工作区)输出 - 文件格式 - FFmpeg视频 - 编码设置等输出 - 后期处理 - 勾选序列编辑器(合成处理选项也可以在这里开关)添加 - 图像序列视频后处理Clipchamp : 剪辑视频,提取音频,提取字幕等分离人声 : https://vocalremover.org/ B-spline 插值 自然边界条件证明 https://dhui626.github.io/index.php/archives/51/ 2023-11-01T06:50:00+00:00 B-spline 插值 自然边界条件证明定理: 四阶(三次) B-spline 插值 的自然边界条件可以简化成如下方程组:$$ \frac{\textbf{d}_{2}-\textbf{d}_{1}}{t_{2}-t_{0}} = \frac{\textbf{d}_{1}-\textbf{d}_{0}}{t_{1}-t_{0}} \\ \frac{\textbf{d}_{n+2}-\textbf{d}_{n+1}}{t_{n}-t_{n-1}} = \frac{\textbf{d}_{n+1}-\textbf{d}_{n}}{t_{n}-t_{n-2}} $$证明:$N_{i,k}(t)$ 参考老师 ppt 的定义,$k$ 是阶数。它的导数为$$ N'_{i,k}(t) = \frac{k}{t_{i+k}-t_i}N_{i,k-1}(t) - \frac{k}{t_{i+k+1}-t_{i+1}}N_{i+1,k-1}(t) $$证明见 Reference1 ,使用了数学归纳法。故 B-spline 的一阶导数为:$$ x(t) = \sum_{i=0}^n N_{i,k}(t) \textbf{d}_i \\ x'(t) = \sum_{i=0}^{n-1} N_{i+1,k-1}(t) \textbf{Q}_i \\ \textbf{Q}_i = \frac{k}{t_{i+k+1}-t_{i+1}}(\textbf{d}_{i+1}-\textbf{d}_{i}) $$推导见 Reference2 。然后可以写出二阶导数的形式如下。$$ x''(t) = \sum_{i=0}^{n-2} N_{i+2,k-2}(t) \textbf{R}_i \\ \textbf{R}_i = \frac{k-1}{t_{i+k+1}-t_{i+2}}(\textbf{Q}_{i+1}-\textbf{Q}_{i}) $$在 B-spline 插值问题中,$k = 4$。指标从 -3 开始。求和范围和 $\textbf{d}_{i}$ 的指标需要相应改变,其他不需要。$$ x(t) = \sum_{i=-3}^{n-1} N_{i,4}(t) \textbf{d}_{i+3} \\ x'(t) = \sum_{i=-3}^{n-2} N_{i+1,3}(t) \textbf{Q}_{i} \\ x''(t) = \sum_{i=-3}^{n-3} N_{i+2,2}(t) \textbf{R}_{i} \\ $$因为 $N_{i,2}(t)$ 只在 $(t_i,t_{i+2})$ 区间非零,边界条件 $x''(t_0)=0$ 等价于如下形式。$$ N_{-1,2}(t_0)\textbf{R}_{-3}=0 $$根据 $\textbf{R}_{i}$ 的表达式,边界条件等价于$$ \textbf{Q}_{-2}=\textbf{Q}_{-3} \\ $$等价于$$ \frac{\textbf{d}_{2}-\textbf{d}_{1}}{t_{3}-t_{-1}} = \frac{\textbf{d}_{1}-\textbf{d}_{0}}{t_{2}-t_{-2}} $$由重结点定义,$t_{-1} = t_{-2} = t_{0}$ ,得到所需的边界条件。 在 $t_n$ 处的自然边界条件也能用同样的方法算出。 Linux初上手记录 https://dhui626.github.io/index.php/archives/25/ 2023-10-28T17:19:00+00:00 当时并没有详细记录的意识,只记录了相关代码,某些步骤现在已经看不懂了xwsl命令备份还原wsl --export Ubuntu C:\OWO\CloudMusic\wslbkp.tar wsl --import Ubuntu C:\CloudMusic C:\OWO\CloudMusic\wslbkp.tar卸载子系统wsl --list --all wsl --unregister Ubuntu安装桌面 gnome(失败)sudo apt-get install ubuntu-desktop gnome安装 systemd(失败)git clone https://github.com/DamionGans/ubuntu-wsl2-systemd-script.git cd ubuntu-wsl2-systemd-script/修改 enter-systemd-namespace 参考bash ubuntu-wsl2-systemd-script.sh //系统会崩溃设置默认Linux开发版wslconfig /setdefault Ubuntu-20.04配置代理(Clash开启允许局域网连接)export hostip=$(cat /etc/resolv.conf |grep -oP '(?<=nameserver\ ).*'); export https_proxy="http://${hostip}:7890"; export http_proxy="http://${hostip}:7890"; export all_proxy="socks5://${hostip}:7891";git 通过代理git clone -c http.proxy="http://127.0.0.1:1080" https://github.com/TIGERB/easy-php.gitapt相关sudo apt -o Acquire::http::proxy="http://${hostip}:7890" install nvidia-cuda-toolkit sudo apt search libdc1394 sudo apt install sudo apt purge libopencv-dev python3-opencv sudo apt autoremoveOpenCV(2.4.11 3.2.0均编译失败,而3.4.5可以无错误编译,下载链接)参考编译用代码mkdir build && cd build cmake .. make -j8 sudo make install sudo ldconfig窗口显示VcXsvr 勾上 Disable access control 选项nano ~/.bashrc最后加上export DISPLAY=`grep -oP "(?<=nameserver ).+" /etc/resolv.conf`:0.0刷新shell的配置source ~/.bashrcDraftnetsh int ipv4 set dynamic tcp start=49152 num=16384相关教程资料Ubuntu桌面入门指南不用装双系统,直接在 Windows 上体验 Linux:Windows Subsystem for Linux - 少数派快速上手──在 Linux 上游玩 osu!stable | 砂糖砂糖沙ORB-SLAM2 “工具安装 和 系统运行“ 详细过程GitHub - DEEPIR/ElasticFusionElasticFusion的编译 - CodeAntennaWindows 10, WSL2 显示 GUI 窗口 Visual Studio 踩坑记录 https://dhui626.github.io/index.php/archives/24/ 2023-10-28T17:04:00+00:00 运行环境:Windows 10 22H2 x64 + Visual Studio 2022vcpkgvcpkg 是 Microsoft 的跨平台开源软件包管理器,极大地简化了 Windows、Linux 和 macOS 上第三方库的配置与安装。官网配置教程Step 1: 从 GitHub 克隆 vcpkggit clone https://github.com/Microsoft/vcpkg.git cd vcpkg注意vcpkg目录的位置,确保文件路径长度合适以及可以存储较大数据。Step 2: 运行 bootstrap./bootstrap-vcpkg.batStep 3: 将包自动集成到 vs 的工程中./vcpkg integrate install之后缺哪个运行库只需在该文件夹打开 powershell 运行 vcpkg 安装指令即可。常用命令搜索包./vcpkg search [packages]安装包(输入上面搜出的包名)./vcpkg install <pkg>查看已安装包列表./vcpkg list删除包./vcpkg remove <pkg>帮助./vcpkg help卸载 vcpkg(并在之后删除此文件夹)./vcpkg integrate remove举例.\vcpkg install eigen3:x64-windows .\vcpkg install opencv4[contrib]:x64-windows .\vcpkg install qt5-base:x64-windows清理空间在文档docs/about/faq.md中提到:## How can I remove temporary files? You can save some disk space by completely removing the `packages\`, `buildtrees\`, and `downloads\` folders.​ 参考 @zhc 笔记,删除buildtrees\可能导致静态库无法调试。网络问题使用代理服务器进行网络加速时,PowerShell 终端默认不走代理端口。为此可以在 PowerShell 中运行:$env:HTTP_PROXY="localhost:7890" $env:HTTPS_PROXY="localhost:7890"上述代理服务器端口因设备而异,仅改变本次端口设置。如果需要设置全局代理,可在环境变量中设置http_proxy http://127.0.0.1:7890/ https_proxy http://127.0.0.1:7890/CMake 时遇到网络问题:在 CMakeLists.txt 的前面添加如下代码set(ENV{http_proxy} "http://127.0.0.1:7890") set(ENV{https_proxy} "http://127.0.0.1:7890")项目配置CMake方法一:使用 CMake-GUI选择源代码位置、build 目录,只需 Configure、Generate、Open Project 三步。若出错则需要对应报错信息找错。大部分错误是找不到依赖库。方法二:使用 VS 内置新建一个空的 VS 项目,文件-打开-CMake,选中 CMakeLists.txt打开CMake设置-高级-CMake生成器-改为VS2022 Win64注意点请勿新建一个项目,然后将代码文件(.cpp .h等)加入项目,折磨且成功率低配置前确认项目可以在win环境生成,如某些依赖库只支持 Linux 系统,需要使用 WSL 生成字体YaHei Consolas Hybrid 1.12Fira Code命令行参数项目-属性-配置属性-调试-命令行参数包含目录出错无法打开源文件:fstream包含目录只要有一个错的,后面的包含目录都会出错。删去不正确的包含目录即可。Eigen 库使用svd 分解Eigen::JacobiSVD<Eigen::Matrix3d> svd(J, Eigen::ComputeFullU| Eigen::ComputeFullV); Eigen::Matrix3d U = svd.matrixU(); Eigen::Matrix3d S = svd.singularValues(); Eigen::Matrix3d V = svd.matrixV(); //J = U * S * V.TLearn C++学习链接:The Cherno的视频系列C++编程基础打开debug模式的代码优化:解决方案属性 - C/C++ - 优化 - 最大优化 、 代码生成 - 基本运行时检查 - 默认输出文件 - 汇编程序输出 - 仅有程序集的列表 (/FA):可在 *.asm 文件查看输出的汇编程序。用这种方法可以查看常量是怎样被优化的。(比如:return 5 * 2 被优化成 mov eax, 10)多行同时输入:alt+鼠标选中位置 或者 alt+shift+方向键选中当前单词:鼠标双击 或者 ctrl+W调试 - 窗口 - 内存:查看当前内存的内容。把想查看的变量拖到地址区域。(string 能看到一些有趣的内容)VS 的输出目录:$(SolutionDir)bin\$(Platform)\$(Configuration)\VS 多项目 library 使用:解决方案-添加-新建项目(编写lib) 添加附加包含目录 当前项目-添加-引用-选中 library 项目高级调试:右键添加条件或操作,并在输出中查看调试信息。预编译头:.cpp 属性 - C/C++ - 预编译头 - 创建; 项目属性 - 预编译头 - 使用; 预编译头文件 - .hVS 编译时间查看:选项 - 项目和解决方案 - 生成计时C++进阶内容类中定义的静态变量:就算创建了多个类元素也共享一个存储空间。C++ 防止创建类的实例:将构造函数写为 private。如 class Log { private:Log(); }; 或将构造函数写为 Log() = delete;C++ 初始化列表:采用如下写法 Player(const std::string& name) : m_Name(name){} 。这种方法可以避免重复初始化,以及const常量只能这样初始化。虚函数写法:需要继承的类函数添加 virtual 前缀。纯虚函数:参考视频28protected : 当前类和派生类可访问到的变量new 关键词分配的内存:生存周期直到它被 delete 或者程序终止。static constexpr int size = 5; int example[size]; // 如果 size 是 const int 会报错std::string 文档:链接一些特殊的字符串定义方式:const wchar_t* chs = L"dhui"; const char16_t* chs2 = u"dhui"; const char32_t* chs3 = U"dhui"; using namespace std::string_literals; //C++14 std::string name0 = "Cherno"s + " hello"; //这种写法允许字符串拼接 const char* name2 = R"(dhui dhui2)"; //这种写法允许回车const int 不可以改变指针指向的内存数据。int const 不可以改变指针让它指向其他东西。mutable 变量:在 const 函数中也可以被更改explicit 关键字:写在类的构造函数前,不允许隐式类型转换std::cout << 运算符重载:std::ostream& operator<<(std::ostream& stream, const Entity& other) { stream << other.GetName() << ", " << other.GetAge(); }智能指针(unique pointer) 与 共享指针(shared pointer) 与 弱指针(weak pointer)std::unique_ptr<Entity> entity(new Entity()); std::shared_ptr<Entity> shardEntity = std::make_shared<Entity>(); std::weak_ptr<Entity> e0 = shardEntity;获取类中的变量的offset:(int)&((Vector3*)0)->x;Templete 写法:template<typename T>C++ 宏:可让代码在不同配置下执行不同的函数,如只让 Debug 模式输出调试信息。 反斜杠 \ 用于换行。为类型定义新的名称:using Devicemap = [type]; typedef [type] Devicemapauto 关键字:传引用 auto&函数指针:一种 confusing 的用法typedef void(*HelloworldFunction)(int); HelloworldFunction function = Helloworld;STL模板库迭代 vector 元素的方法:for (Vertex& v : vertices); 最好传引用删除一个 vector 元素:vertices.erase(vertices.begin() + 1);为 vector 预分配空间 vertices.reserve(3); (有别于resize,之后可以push_back)使用 vertices.emplace_back(1, 2, 3); 避免类重新被 copy constructor 构建array: std::array<int,5> data; 可以调用 data.size() 函数。在栈上开辟内存,而 vector 在堆上。Lambda 函数:参考。传入函数可能需要 std::function 。部分代码如下#include <functional> void print(int value, const std::function<void(int)>& func) { func(value); } int a = 5; auto lambda = [&](int value) { std::cout << "Value:" << value << "\t a=" << a << std::endl; }; print(9, lambda);std::find_if 的一个应用示例:std::vector<int> values = { 1, 5, 4, 2, 3 }; auto it = std::find_if(values.begin(), values.end(), [](int value) {return value > 3; });std::map 与 std::unordered_map:建立两者的关系,类似数组。第一个必须是 hashable 的,如指针,否则要写个 hash 函数。遍历 std::map :若要有序输出,对于第一个变量要有 operator< 函数重载。视频演示for (auto& [name, city] : cityMap){} // C++17 for (auto& kv : cityMap){ kv.first; kv.second; } std::thread :分出一个线程干别的事情,并继续后面的代码。std::thread worker(DoWork); // Do something worker.join();thread_local 关键字:让每个线程中创建一个实例,互不干扰。计时函数 Chronoauto start = std::chrono::high_resolution_clock::now(); // Do something auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration<float> duration = end - start; std::cout << "Time = " << duration.count() << std::endl;或者直接构建结构体,用于计时。在需计时的函数中创建变量 Timer timer; 注意 timer 的生存周期。struct Timer { std::chrono::time_point<std::chrono::steady_clock> start, end; std::chrono::duration<float> duration; Timer() { start = std::chrono::high_resolution_clock::now(); } ~Timer() { end = std::chrono::high_resolution_clock::now(); duration = end - start; std::cout << "Timer took = " << duration.count() * 1000.0f << "ms" << std::endl; } };std::sort 时间复杂度:$O(NlogN)$static_cast / dynamic_cast :后者会更加安全,涉及类的继承关系时可使用后者。多返回值: std::tuple / std::pair (后者仅允许双返回值)std::tuple<std::string, int> person = { "Cherno", 24 }; //初始化 std::string& name = std::get<0>(person); //取元素 std::tie(name, std::ignore) = person; //解包std::optional (C++17)std::optional<int> count = {}; if (count.has_value()) {}; // 判断 count 有没有值 int c = count.value_or(100); std::variant (C++17)std::variant<std::string, int> data; data = "Cherno"; data.index(); // 判断data的类型std::any (C++17) std::async 写法较复杂,但可以调试查看每个线程正在执行的任务(调试->窗口->并行堆栈) 视频参考std::string_view 用于读取string数据,而不用初始化stringbenchmarking: 生成 json 文件导入到 chrome://tracing 中, 代码完结于 2024.6.5,后续教程 (SINGLETON开始) 基本是 C++20 或是更加进阶的 C++ 技巧,需要用到的时候再针对性学习。 Jellyfin 折腾记录 https://dhui626.github.io/index.php/archives/23/ 2023-10-28T16:57:00+00:00 运行环境:Windows 10 22H2 x64 + Jellyfin Server 10.8.11介绍Jellyfin官网 + 文档查看官网介绍,本应用是一种媒体存储方案,并附加共享功能,可以搭建自己的媒体服务器网络。该应用具有多平台支持,只要有浏览器即可。该软件免费,now and always。安装利用 Jellyfin + Bangumi 打造更舒适的动画媒体库安装后的设置可参考如上文章,笔者在安装结束之后才看到本文。密码可以留空。转码设置默认也行,博客作者建议全部勾选。插件安装:「插件 - 存储库」点击加号,添加如下网址:https://jellyfin-plugin-bangumi.pages.dev/repository.json然后在「插件 - 目录 - 元数据」找到 Bangumi 插件安装,重启 Jellyfin媒体库设置动画:内容类型选择「节目」命名规则:将文件名加上 Season 和 Episode 信息。示例:Shows ├── Series (2010) │ ├── Season 00 │ │ ├── Some Special.mkv │ │ ├── Episode S00E01.mkv │ │ └── Episode S00E02.mkv │ ├── Season 01 │ │ ├── Episode S01E01-E02.mkv │ │ ├── Episode S01E03.mkv │ │ └── Episode S01E04.mkv │ └── Season 02 │ ├── Episode S02E01.mkv │ ├── Episode S02E02.mkv │ ├── Episode S02E03 Part 1.mkv │ └── Episode S02E03 Part 2.mkv └── Series (2018) ├── Episode S01E01.mkv ├── Episode S01E02.mkv ├── Episode S02E01-E02.mkv └── Episode S02E03.mkv重命名教程:利用 Renamer Pro 的插入 + 序列化功能。@miracle 的建议:不需要重命名,Jellyfin会自动识别。且若文件夹名和种子文件相同,还可以做种。但根据测试,季度信息文件夹,如多季度番剧的 S01~S0x 文件夹还是需要创建并拖进相应视频的。 电影:内容类型选择「电影」三次元电影 bangumi 索引不到,可以提高 tmdb 的优先级。ass 字幕出现方块字:播放 - 备用字体文件路径漫画:内容类型选择「照片」添加相应的文件夹后需要手动扫描媒体库,以获得漫画封面信息。书籍:内容类型选择「书籍」能识别 epub 但不能识别 txt 文件,需要手动转换。且 epub 不会生成封面。音乐:内容类型选择「音乐」建议按专辑建立文件夹存放。服务器建立测试 IPv6 连接 Jellyfin 联网设置中开启 IPv4, IPv6 功能。如果运气很好,网络环境有公网 IPv4,可以用 http://[IPv4地址]:8096/ 访问。如果设置得当,网络环境有公网 IPv6,可以用 http://[IPv6地址]:8096/ 访问。目前大部分网络没有 IPv4,但支持打开 IPv6,需在路由器中设置。而有些学校的宿舍网络并不支持 IPv6,更别说 IPv4 了,有如下两种解决办法:使用流量网络(这总支持 IPv6 了吧,不行的话直接 call 运营商总部)反向代理反向代理设置教程:使用 frp:需要有 VPS(没有,遂搁置)教程:使用frp进行内网穿透 frp 内网穿透神器搭建 萌新也看得懂的教程系列使用 SakuraFrp:注册登录下载安装,一气呵成。参考教程:HTTP(S) 协议穿透指南隧道类型选 TCP,海外节点支持 http 协议,但会经常断线重连,故选择内地节点。新建穿透隧道 - 输入本地 ip 和端口 - 选择穿透结点(ping一下)- 创建内地节点 + http 无法正常访问:隧道列表 - 编辑 - 打开自动 HTTPS Chrome 浏览器会提示连接不安全。这不对劲,虽然已经实现目标了,但不安全Jellyfin 开启 https 访问:没有 ssl 证书咋整啊?可以自建。参考下载 openssl:Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions若安装步骤中未勾选 Copy OpenSSL DLLs to: The Windows system directory,需要手动添加环境变量。生成私钥文件openssl genrsa -des3 -out localhost.key 2048去除口令openssl rsa -in localhost.key -out localhost.key创建请求证书openssl req -new -key localhost.key -out localhost.csr生成证书openssl x509 -req -days 36500 -in localhost.csr -signkey localhost.key -out localhost.crt这样就生成了三个文件:localhost.crt localhost.csr localhost.key然后将证书文件转换为 Jellyfin 能读取的 PFX 文件:网站1 网站2Jellyfin 控制台 - 联网 - 启用 HTTPS + 自定义 SSL证书路径(选择刚才转换完成的 pfx 文件)。但 Chrome 打开网站还是会显示不安全!但至少能用了。安全证书颁发方法:使用 Active Directory 证书服务 教程 。参考这篇文章?本地安排上HTTPS的最佳途径~ 暂时搁置。 测试数学公式 https://dhui626.github.io/index.php/archives/6/ 2023-10-28T12:49:00+00:00 行间公式测试:$$ a + \frac{|ac| \vec{n_1}+|ab| \vec{n_2}}{2 sin\theta} $$行内公式测试:其中 $\vec{n_1}$ 和 $\vec{n_2}$ 分别是垂直于 $ab$ 和垂直于 $ac$ 的单位向量,$\theta$ 是 $ab$ 和 $ac$ 的夹角。平移两条垂线组成一个平行四边形易验证外心关系。 个人网站 搭建记录 https://dhui626.github.io/index.php/archives/3/ 2023-10-26T15:11:00+00:00 个人网站 搭建记录运行环境:Windows 10 22H2软件版本:Apache 2.4 + PHP 8.2.12 + MySQL 8.2.0搭建教程准备安装 Typecho 进行搭建网页测试。下载下来没有html,诶??? php 是什么啊,打开怎么是源码啊。此处省略一万字,去学习了静态网页和动态网页的区别。安装 php 环境首先安装 php 环境,在 Windows 系统下有集成式安装软件 Wampserver,一键安装。但是这东西又丑又卡,还不断弹出 cmd 窗口让我觉得是病毒软件,虽然在上面搭建成功了但也反手卸载了。不如自己动手安装!参考教程:记一次windows配置PHP环境。难得的优质教程,跟着他的教程来基本没有搜索别的内容了。1 安装Apache2.41.1 Apache 的下载链接 The Apache HTTP Server Project1.2 点击 a number of third party vendors 下载 windows 版本1.3 选择 ApacheHaus1.4 选择 x64 的版本下载1.5 建立个人主页文件夹 Home,将下载的 apache 解压到其中。1.6 用记事本打开 conf 中的 httpd.conf,找到如下代码段Define SRVROOT "/Apache24" ServerRoot "${SRVROOT}"将引号内的内容改为 Apache 的路径。Define SRVROOT "E:/CloudMusic/VSCode/Home/Apache24" ServerRoot "${SRVROOT}"1.7 更改端口号Listen 80默认端口号是80,浏览器输入 localhost 就能访问,可以改为其他Listen 97001.8 用管理员身份打开 cmd,然后进入 apache 的 bin 路径,用 httpd -k install 进行安装1.9 安装完成之后在 /Apache24/bin 中打开 ApacheMonitor.exe 并启用服务。1.10 验证安装,在浏览器输入localhost:9700 如果打开 apache 的首页即为安装成功。2 安装PHP2.1 下载 PHP8.2,直接到官网下载即可,笔者选择的版本是 VS16 x64 Thread Safe (2023-Oct-24 21:57:24)2.2 解压到个人主页文件夹中2.3 打开PHP的目录将 php.ini-development 先复制一份备份,然后把 php.ini-development 改为 php.ini 保存2.4 打开 php.ini 修改配置,查找;extension_dir = "ext"改为 extension_dir = "ext的目录",比如extension_dir = "E:/CloudMusic/VSCode/Home/PHP/ext"2.5 打开 apache/conf 的 httpd.conf,在 DirectoryIndex 后加上 index.php<IfModule dir_module> DirectoryIndex index.html index.php </IfModule>2.6 开启 rewrite 功能:将下面这行代码前面的 # 去掉(httpd.conf中)#LoadModule rewrite_module modules/mod_rewrite.so2.7 加载PHP模块,在 httpd.conf 中加入以下代码#php8 LoadModule php_module E:/CloudMusic/VSCode/Home/PHP/php8apache2_4.dll <IfModule php_module> PHPIniDir "E:/CloudMusic/VSCode/Home/PHP/" AddType application/x-httpd-php .php AddType application/x-httpd-php-source .phps </IfModule>2.8 验证,注释 apache24/htdocs 中 index.html 的网页代码,输入下边这个输入下边这个 Hello World 代码,然后重命名为 index.php.<?php echo"hello world" ?>在电脑浏览器输入 localhost:9700 , 若能正确显示 hello world , 则 php 网页已经能够显示了。3 安装mysql3.1 官网下载链接。笔者选择的是 mysql-8.2.0-winx64.msi3.2 直接安装的话可能会提示缺少 vs2019 的 redistributable. 到微软官网下载安装 VC_redist.x64.exe3.3 以管理员身份进入cmd命令行。执行cd C:\Program Files\MySQL\MySQL Server 8.2\bin mysqld.exe --install mysqld --initialize3.4 在 win+r 之后输入 services.msc 进入本地服务管理,启动 mysql 服务。3.5 登录需要输入密码。在 C:\Program Files\MySQL\MySQL Server 8.2\data 中后缀名为 err 的文件中找到临时密码,搜索如下字段A temporary password is generated for root@localhost: &baRyjS-b5mp3.6 输入 mysql -u root -p 和密码进行登录。登录之后修改密码。 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';3.7 输入如下代码创建数据库create DATABASE home;4 安装typecho4.1 进入 /Apache24/htdocs 目录,将 typecho 解压到此处。在浏览器中打开 localhost:97004.2 安装提示缺少拓展,需要安装所需拓展。将 php.ini 对应的分号去掉即可。;extension=mbstring ;extension=openssl ;extension=pdo_mysql4.3 继续安装,数据库名称填 home,数据库密码填修改后的密码,其余问题不大。4.4 安装完成后登录控制台,可以进行网页管理等操作。4.5 第三方主题安装:解压到 /usr/themes ,插件安装:解压到 /usr/plugins ,启用即可。4.6 若第三方主题启用失败建议查看 github issue 排查问题。5 网站设置主题设置可以在 控制台-外观-设置外观 里找到,在此处启用数学公式解析。设置-基本设置-站点地址,可以更改站点地址。启用https如果不关心网站的“不安全”提示,SSL 证书可以暂时不管。首先登录 Typecho 后台 -> 设置 -> 基本设置 -> 站点地址改成 https 的域名然后编辑 Typecho 站点根目录下的文件config.inc.php加入下面一行配置。/** 开启HTTPS */ define('__TYPECHO_SECURE__',true);然后在站点主题目录下找到comments.php文件,并搜索到$this->commentUrl(),将其修改为:echo str_replace("http","https",$this->commentUrl()),然后点击保存即可。在开启 https 之后,网站的所有图片外链都需要修改为 https 外链,否则无法正常加载。内网穿透设置使用 SakuraFrp,设置本地端口为 443 即可。在网站未启用 https 的情况下,开启 “强制 https” 会有 bug,会把 http 请求都转换为 https,一些本地的图片资源链接 http://localhost/xxx 也会被强制转换为 https://dhui626.github.io/xxx ,导致无法正常显示。建议图片外链选择 github.io ,作为免费的图床。站点地址改成 https://dhui626.github.io 之后,还是会有 bug,在本地能打开网页,但在其他设备打开无法正常显示。需要将站点地址改为内网穿透地址。如笔者的 https://frp-oak.top:56651/。改了之后用 localhost 还是能登陆的,不用担心不小心把内网穿透隧道删除了而再也进不去了的问题。首页静态Html生成参考 Typecho生成首页静态HTML数倍提高网站打开速度在网站根目录创建一个php文件,重命名为static.php<?php $nowtime=time(); $pastsec = $nowtime - $_GET["t"]; if($pastsec<600){ exit; //10分钟更新一次,时间可以自己调整 } ob_start(); //打开缓冲区 include("index.php"); $content = ob_get_contents(); //得到缓冲区的内容 $content .= "\n<script language=javascript src=\"static.php?t=".$nowtime."\"></script>"; //加上调用更新程序的代码 file_put_contents("index.html",$content); if (!function_exists("file_put_contents")){ function file_put_contents($fn,$fs){ $fp=fopen($fn,"w+"); fputs($fp,$fs); fclose($fp); } } ?>设置网站优先打开 index.html 而不是index.php,即可在每次打开 html 提高速度,且会根据设定的时间间隔更新。全站静态Html生成参考 typecho全站静态化方案 、 typecho完全静态化因动态网站部署麻烦,许多站点仅支持静态网站,如 github.io 。本方法可以导出全站的静态html。创建以下脚本并命名为staticpass.php .上述参考的代码是 Linux 环境下的代码,笔者已将其转化为 Windows 代码。需要手动安装 wget .注意 url 是需要爬虫的网页地址,rurl是需要部署静态网页的地址,需要相应修改。<?php $url = 'https://dhui626.github.io'; //网址,不能以"/"结尾 $rurl= ''; //要替换成路径或网址,可为空,不能以"/"结尾 $dir = __DIR__ . "/" . str_replace('https://', '', str_replace('http://', "", $url)); exec("cls",$clc); echo $clc[0]; echo "开始下载文件\r\n"; exec("RMDIR /S /Q {$dir}",$return); //小心调用! exec("wget --no-check-certificate -r -p -np {$url}",$return); $dirs = get_filenamesbydir($dir); //不处理非html文件 for ($i = 0; $i < count($dirs); $i++) { $file=str_replace(__DIR__, "", $dirs[$i]['file']); if (!preg_match("/html/",$file) ) { //删除对应的元素 echo "\r\n不处理文件:\r\n"; echo $file; unset($dirs[$i]); } } array_filter($dirs); sort($dirs);//重新生成索引下标 //网址处理 $count=count($dirs); for ($i = 0; $i < $count; $i++) { // echo $url; // echo $rurl; $content=str_replace($url,$rurl,file_get_contents($dirs[$i]['file'])); // echo $dirs[$i]['file']; file_put_contents($dirs[$i]['file'],$content); $n=$i+1; exec("cls",$clc); echo $clc[0]; echo "文件下载完毕\r\n"; echo "开始处理文件,共{$count}个文件需要处理,已处理{$n}个\r\n"; } echo "处理完毕,文件目录:{$dir}\r\n"; function get_allfiles($path, &$files) { if (is_dir($path)) { $dp = dir($path); while ($file = $dp->read()) { if ($file !== "." && $file !== "..") { get_allfiles($path . "/" . $file, $files); } } $dp->close(); } if (is_file($path)) { $files[] = ['file' => $path]; } } function get_filenamesbydir($dir) { $files = array(); get_allfiles($dir, $files); return $files; }执行cd E:\CloudMusic\VSCode\Home\Apache24\htdocs php staticpass.php注意 "php 绝对目录下的staticpass.php" 代码会在当前目录(如未设置php环境变量就是在php根目录中)创建,而不是站点目录,笔者因为这个愚蠢的问题调试了一个多小时的 bug。php代码调试参考 vscode调试php(解决vscode远程调试无效的问题)但因为静态网站转换的代码无问题,暂时不打算研究 php 调试相关的问题。参考资料博客范例参考链接希卡米 | HiKami:Theme Argon By solstice23初之音:Powered by Typecho Theme VOIDEdNovas 的小站 :Framework Hexo Theme Butterfly静态网页模板参考链接(没用上)FreeHtml5HTML5 UPWeb开发学习链接mdn web docsEnd 欢迎使用 Typecho https://dhui626.github.io/index.php/archives/1/ 2023-10-26T14:49:00+00:00 如果您看到这篇文章,表示您的 blog 已经安装成功.