首页
关于
壁纸
直播
留言
友链
统计
Search
1
《吞食天地1》金手指代码
8,022 阅读
2
白嫖Emby
6,979 阅读
3
Emby客户端IOS破解
6,939 阅读
4
《三国志英杰传》攻略
6,798 阅读
5
破解emby-server
4,597 阅读
moonjerx
game
age-of-empires
zx3
san-guo-zhi
尼尔:机械纪元
net
emby
learn-video
docker
torrent
photoshop
route
minio
git
ffmpeg
im
vue
gitlab
typecho
svn
alipay
nasm
srs
mail-server
tailscale
kkfileview
aria2
webdav
synology
redis
oray
chemical
mxsite
math
π
x-ui
digital-currency
server
nginx
baota
k8s
http
cloud
linux
shell
database
vpn
esxi
rancher
domain
k3s
ewomail
os
android
windows
ios
app-store
macos
develop
java
javascript
uniapp
nodejs
hbuildx
maven
android-studio
jetbrain
jenkins
css
mybatis
php
python
hardware
hard-disk
pc
RAM
software
pt
calibre
notion
office
language
literature
philosophy
travel
登录
Search
标签搜索
ubuntu
mysql
openwrt
zerotier
springboot
centos
openvpn
jdk
吞食天地2
synology
spring
idea
windows11
吞食天地1
transmission
google-play
Japanese
xcode
群晖
kiftd
MoonjerX
累计撰写
383
篇文章
累计收到
466
条评论
首页
栏目
moonjerx
game
age-of-empires
zx3
san-guo-zhi
尼尔:机械纪元
net
emby
learn-video
docker
torrent
photoshop
route
minio
git
ffmpeg
im
vue
gitlab
typecho
svn
alipay
nasm
srs
mail-server
tailscale
kkfileview
aria2
webdav
synology
redis
oray
chemical
mxsite
math
π
x-ui
digital-currency
server
nginx
baota
k8s
http
cloud
linux
shell
database
vpn
esxi
rancher
domain
k3s
ewomail
os
android
windows
ios
app-store
macos
develop
java
javascript
uniapp
nodejs
hbuildx
maven
android-studio
jetbrain
jenkins
css
mybatis
php
python
hardware
hard-disk
pc
RAM
software
pt
calibre
notion
office
language
literature
philosophy
travel
页面
关于
壁纸
直播
留言
友链
统计
搜索到
383
篇与
moonjerx
的结果
2026-04-29
用 FFmpeg + BAT 批处理打造视频工具箱:踩坑全记录
记录一次从零开始编写 Windows 批处理视频工具箱的完整过程,重点整理调试途中踩到的经典 CMD 坑。工具最终实现了视频掐头去尾、多种合并模式、旋转、分辨率预处理、参数对比统一等功能。最终脚本@echo off chcp 936 >nul setlocal enabledelayedexpansion :: 配置项: 是否显示ffmpeg编码输出 (1=显示, 0=隐藏) set "SHOW_LOG=1" title 视频工具箱 :MENU cls echo ========================================== echo 视频工具箱 (FFmpeg) echo ========================================== echo. echo 1. 移除视频开头 (掐头) echo 2. 移除视频结尾 (去尾) echo 3. 合并多个视频 (直接合并) echo 4. 合并多个视频 (自动统一分辨率) echo 5. 旋转视频 - 快速 (仅修改标记) echo 6. 旋转视频 - 真实 (重新编码) echo 7. 预处理视频分辨率 (填充黑边) echo 8. 预处理视频参数 (对比并统一) echo 9. 退出 echo. echo ========================================== set /p choice="请输入选项 (1-9): " if "%choice%"=="1" goto MODE_CUT_START if "%choice%"=="2" goto MODE_CUT_END if "%choice%"=="3" goto MODE_MERGE if "%choice%"=="4" goto MODE_MERGE_PAD if "%choice%"=="5" goto MODE_ROTATE_FAST if "%choice%"=="6" goto MODE_ROTATE_REAL if "%choice%"=="7" goto MODE_PAD if "%choice%"=="8" goto MODE_PREPROCESS if "%choice%"=="9" exit /b goto MENU :: ========================================== :: 模式 1: 移除开头 :: ========================================== :MODE_CUT_START cls echo [模式: 移除开头] echo. set /a file_count=0 set /a index=0 echo 序号 文件名 echo ---------------------------------------- for /f "delims=" %%i in ('dir /b *.mp4 *.mov *.m4v 2^>nul') do ( set "tn=%%i" echo !tn! | findstr /i "_out _rotated _padded _handle" >nul if errorlevel 1 ( set /a index+=1 set "file_!index!=%%i" set /a file_count+=1 echo !index!. %%i ) ) if !file_count! equ 0 (echo 未找到视频文件 & pause & goto MENU) echo. set /p sel="输入序号(逗号分隔): " if "%sel%"=="" goto MENU set /p sec="移除开头秒数: " if "%sec%"=="" goto MENU set "sel=%sel: =%" set "sel=%sel:,= %" for %%n in (%sel%) do ( call set "vf=%%file_%%n%%" echo 处理: !vf! if "%SHOW_LOG%"=="1" ( for /f "delims=" %%f in ("!vf!") do ffmpeg -ss %sec% -i "!vf!" -map 0 -c:v copy -c:a copy -map_metadata 0 "%%~nf_out%%~xf" -y ) else ( for /f "delims=" %%f in ("!vf!") do ffmpeg -ss %sec% -i "!vf!" -map 0 -c:v copy -c:a copy -map_metadata 0 "%%~nf_out%%~xf" -y -loglevel error ) if !errorlevel! equ 0 (echo 成功) else (echo 失败) ) pause & goto MENU :: ========================================== :: 模式 2: 移除结尾 :: ========================================== :MODE_CUT_END cls echo [模式: 移除结尾] echo. set /a file_count=0 set /a index=0 echo 序号 文件名 echo ---------------------------------------- for /f "delims=" %%i in ('dir /b *.mp4 *.mov *.m4v 2^>nul') do ( set "tn=%%i" echo !tn! | findstr /i "_out _rotated _padded _handle" >nul if errorlevel 1 ( set /a index+=1 set "file_!index!=%%i" set /a file_count+=1 echo !index!. %%i ) ) if !file_count! equ 0 (echo 未找到视频文件 & pause & goto MENU) echo. set /p sel="输入序号(逗号分隔): " if "%sel%"=="" goto MENU set /p rmsec="移除结尾秒数: " if "%rmsec%"=="" goto MENU set "sel=%sel: =%" set "sel=%sel:,= %" for %%n in (%sel%) do ( call set "vf=%%file_%%n%%" echo 处理: !vf! ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "!vf!" > temp_dur.txt 2>nul set /p dur=<temp_dur.txt del temp_dur.txt 2>nul for /f %%b in ('powershell -command "[math]::Round([double]'!dur!' - %rmsec%, 3)"') do set keep=%%b echo 保留: !keep! 秒 if "%SHOW_LOG%"=="1" ( for /f "delims=" %%f in ("!vf!") do ffmpeg -i "!vf!" -t !keep! -map 0 -c:v copy -c:a copy -map_metadata 0 "%%~nf_out%%~xf" -y ) else ( for /f "delims=" %%f in ("!vf!") do ffmpeg -i "!vf!" -t !keep! -map 0 -c:v copy -c:a copy -map_metadata 0 "%%~nf_out%%~xf" -y -loglevel error ) if !errorlevel! equ 0 (echo 成功) else (echo 失败) ) pause & goto MENU :: ========================================== :: 模式 3: 直接合并 :: ========================================== :MODE_MERGE cls echo [模式: 合并视频 (直接合并)] echo. set /a file_count=0 set /a index=0 echo 序号 文件名 echo ---------------------------------------- for /f "delims=" %%i in ('dir /b *.mp4 *.mov *.m4v 2^>nul') do ( set /a index+=1 set "file_!index!=%%i" set /a file_count+=1 echo !index!. %%i ) if !file_count! equ 0 (echo 未找到视频文件 & pause & goto MENU) echo. set /p sel="输入序号(逗号分隔): " if "%sel%"=="" goto MENU del temp_list.txt 2>nul set "sel=%sel: =%" set "sel=%sel:,= %" for %%n in (%sel%) do ( call set "tmpf=%%file_%%n%%" echo file '!tmpf!' >> temp_list.txt ) echo 合并中... if "%SHOW_LOG%"=="1" ( ffmpeg -f concat -safe 0 -i temp_list.txt -c copy -y merged_out.mp4 ) else ( ffmpeg -f concat -safe 0 -i temp_list.txt -c copy -y merged_out.mp4 -loglevel error -stats ) if exist merged_out.mp4 ( echo 成功: merged_out.mp4 del temp_list.txt 2>nul ) else ( echo 失败 ) pause & goto MENU :: ========================================== :: 模式 4: 合并视频 (全自动 - 统一所有参数后合并) :: ========================================== :MODE_MERGE_PAD cls echo [模式: 合并视频 - 全自动统一参数并合并] echo. set /a file_count=0 set /a index=0 echo 序号 文件名 echo ---------------------------------------- for /f "delims=" %%i in ('dir /b *.mp4 *.mov *.m4v 2^>nul') do ( set /a index+=1 set "file_!index!=%%i" set /a file_count+=1 echo !index!. %%i ) if !file_count! equ 0 (echo 未找到视频文件 & pause & goto MENU) echo. set /p sel="输入序号(逗号分隔): " if "%sel%"=="" goto MENU del temp_sel.txt temp_list.txt temp_merge_*.mp4 2>nul set "sel=%sel: =%" set "sel=%sel:,= %" for %%n in (%sel%) do ( call set "tmpf=%%file_%%n%%" echo !tmpf! >> temp_sel.txt ) :: 读取所有文件信息 set /a maxw=0 set /a maxh=0 set /a sel_count=0 for /f "delims=" %%f in (temp_sel.txt) do ( set /a sel_count+=1 echo %%f > temp_cur.txt set /p cur_file=<temp_cur.txt del temp_cur.txt 2>nul set "sel_file_!sel_count!=!cur_file!" ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 "!cur_file!" > temp_w.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 "!cur_file!" > temp_h.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of csv=s=x:p=0 "!cur_file!" > temp_br.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=time_base -of csv=s=x:p=0 "!cur_file!" > temp_tb.txt 2>nul set /p tw=<temp_w.txt set /p th=<temp_h.txt set /p tbr=<temp_br.txt set /p ttb=<temp_tb.txt del temp_w.txt temp_h.txt temp_br.txt temp_tb.txt 2>nul set /a tw=!tw!+0 set /a th=!th!+0 set "sel_w_!sel_count!=!tw!" set "sel_h_!sel_count!=!th!" set "sel_br_!sel_count!=!tbr!" set "sel_tb_!sel_count!=!ttb!" if !tw! gtr !maxw! set /a maxw=!tw! if !th! gtr !maxh! set /a maxh=!th! ) del temp_sel.txt 2>nul :: 展示对比信息 echo. echo ========================================== for /L %%i in (1,1,%sel_count%) do ( echo [%%i] !sel_file_%%i! echo 分辨率: !sel_w_%%i! x !sel_h_%%i! time_base: !sel_tb_%%i! ) echo. echo 目标分辨率: !maxw! x !maxh! 目标time_base: 1/90000 echo ========================================== echo. :: 逐个处理并生成临时文件 for /L %%i in (1,1,%sel_count%) do ( echo %%i > temp_idx.txt echo !sel_file_%%i! > temp_cf.txt echo !sel_w_%%i! > temp_vw.txt echo !sel_h_%%i! > temp_vh.txt echo !sel_tb_%%i! > temp_vtb.txt echo !sel_br_%%i! > temp_vbr.txt set /p cur_file=<temp_cf.txt set /p vw=<temp_vw.txt set /p vh=<temp_vh.txt set /p vtb=<temp_vtb.txt set /p vbr=<temp_vbr.txt del temp_cf.txt temp_vw.txt temp_vh.txt temp_vtb.txt temp_vbr.txt temp_idx.txt 2>nul set /a vw=!vw!+0 set /a vh=!vh!+0 set /a vbr=!vbr!+0 echo [%%i] !cur_file! set "need_pad=1" if "!vw!"=="!maxw!" if "!vh!"=="!maxh!" set "need_pad=0" set "need_tb=1" echo !vtb! > temp_check.txt findstr /x "1/90000" temp_check.txt >nul 2>nul if not errorlevel 1 set "need_tb=0" del temp_check.txt 2>nul if "!need_pad!"=="1" ( echo 填充分辨率 + 统一time_base set /a px=maxw - vw set /a px=px / 2 set /a py=maxh - vh set /a py=py / 2 ffmpeg -noautorotate -i "!cur_file!" -vf "pad=!maxw!:!maxh!:!px!:!py!:black" -c:v libx264 -preset fast -b:v !vbr! -video_track_timescale 90000 -c:a copy "temp_merge_%%i.mp4" -y -loglevel error if exist "temp_merge_%%i.mp4" ( echo 完成 echo file 'temp_merge_%%i.mp4' >> temp_list.txt ) else ( echo 失败 ) ) if "!need_pad!"=="0" if "!need_tb!"=="1" ( echo 统一time_base ffmpeg -i "!cur_file!" -c copy -video_track_timescale 90000 "temp_merge_%%i.mp4" -y -loglevel error if exist "temp_merge_%%i.mp4" ( echo 完成 echo file 'temp_merge_%%i.mp4' >> temp_list.txt ) else ( echo 失败 ) ) if "!need_pad!"=="0" if "!need_tb!"=="0" ( echo 参数一致,直接使用 echo file '!cur_file!' >> temp_list.txt ) echo. ) echo 合并中... ffmpeg -f concat -safe 0 -i temp_list.txt -c copy -y merged_out.mp4 -loglevel error -stats if exist merged_out.mp4 ( echo. echo 成功: merged_out.mp4 del temp_list.txt temp_merge_*.mp4 2>nul ) else ( echo 失败 ) pause & goto MENU :: ========================================== :: 模式 5: 旋转视频 - 快速 :: ========================================== :MODE_ROTATE_FAST cls echo [模式: 旋转视频 - 快速] echo. set /a file_count=0 set /a index=0 echo 序号 文件名 echo ---------------------------------------- for /f "delims=" %%i in ('dir /b *.mp4 *.mov *.m4v 2^>nul') do ( set "tn=%%i" echo !tn! | findstr /i "_rotated" >nul if errorlevel 1 ( set /a index+=1 set "file_!index!=%%i" set /a file_count+=1 echo !index!. %%i ) ) if !file_count! equ 0 (echo 未找到视频文件 & pause & goto MENU) echo. set /p sel="输入序号(逗号分隔): " if "%sel%"=="" goto MENU echo. echo 1. 左转90度 echo 2. 右转90度 echo 3. 旋转180度 set /p rc="请选择: " if "%rc%"=="1" set "rv=270" if "%rc%"=="2" set "rv=90" if "%rc%"=="3" set "rv=180" if not defined rv goto MODE_ROTATE_FAST set "sel=%sel: =%" set "sel=%sel:,= %" for %%n in (%sel%) do ( call set "vf=%%file_%%n%%" echo 处理: !vf! for /f "delims=" %%f in ("!vf!") do ffmpeg -i "!vf!" -map 0 -c copy -metadata:s:v:0 rotate=%rv% "%%~nf_rotated%%~xf" -y -loglevel error if !errorlevel! equ 0 (echo 成功) else (echo 失败) ) pause & goto MENU :: ========================================== :: 模式 6: 旋转视频 - 真实 :: ========================================== :MODE_ROTATE_REAL cls echo [模式: 旋转视频 - 真实重编码] echo. set /a file_count=0 set /a index=0 echo 序号 文件名 echo ---------------------------------------- for /f "delims=" %%i in ('dir /b *.mp4 *.mov *.m4v 2^>nul') do ( set "tn=%%i" echo !tn! | findstr /i "_rotated" >nul if errorlevel 1 ( set /a index+=1 set "file_!index!=%%i" set /a file_count+=1 echo !index!. %%i ) ) if !file_count! equ 0 (echo 未找到视频文件 & pause & goto MENU) echo. set /p sel="输入序号(逗号分隔): " if "%sel%"=="" goto MENU echo. echo 1. 左转90度 echo 2. 右转90度 echo 3. 旋转180度 set /p rc="请选择: " if "%rc%"=="1" set "tv=2" if "%rc%"=="2" set "tv=1" if "%rc%"=="3" set "tv=2,transpose=2" if not defined tv goto MODE_ROTATE_REAL set "sel=%sel: =%" set "sel=%sel:,= %" for %%n in (%sel%) do ( call set "vf=%%file_%%n%%" echo 处理: !vf! if "%SHOW_LOG%"=="1" ( for /f "delims=" %%f in ("!vf!") do ffmpeg -i "!vf!" -vf "transpose=%tv%" -c:v libx264 -preset fast -crf 18 -c:a copy "%%~nf_rotated%%~xf" -y ) else ( for /f "delims=" %%f in ("!vf!") do ffmpeg -i "!vf!" -vf "transpose=%tv%" -c:v libx264 -preset fast -crf 18 -c:a copy "%%~nf_rotated%%~xf" -y -loglevel error -stats ) if !errorlevel! equ 0 (echo 成功) else (echo 失败) ) pause & goto MENU :: ========================================== :: 模式 7: 预处理视频分辨率 :: ========================================== :MODE_PAD cls echo [模式: 预处理视频分辨率] echo. set /a file_count=0 set /a index=0 echo 序号 分辨率(宽x高) 文件名 echo ---------------------------------------- for /f "delims=" %%i in ('dir /b *.mp4 *.mov *.m4v 2^>nul') do ( set /a index+=1 set "file_!index!=%%i" set /a file_count+=1 ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 "%%i" > temp_w.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 "%%i" > temp_h.txt 2>nul set /p fw=<temp_w.txt set /p fh=<temp_h.txt del temp_w.txt temp_h.txt 2>nul echo !index!. !fw! x !fh! %%i ) if !file_count! equ 0 (echo 未找到视频文件 & pause & goto MENU) echo. set /p sel="输入序号: " if "%sel%"=="" goto MENU call set "vf=%%file_%sel%%%" echo. echo 选中: !vf! echo. echo 请输入目标分辨率,格式: 宽,高 echo 例如当前视频是 720x400,想填充到 720x404,输入: 720,404 echo. set /p res="目标分辨率(宽,高): " if "%res%"=="" goto MENU for /f "tokens=1,2 delims=," %%a in ("%res%") do ( set /a target_w=%%a set /a target_h=%%b ) echo 目标分辨率: !target_w!(宽) x !target_h!(高) ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 "!vf!" > temp_w.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 "!vf!" > temp_h.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of csv=s=x:p=0 "!vf!" > temp_br.txt 2>nul set /p vw=<temp_w.txt set /p vh=<temp_h.txt set /p vbr=<temp_br.txt del temp_w.txt temp_h.txt temp_br.txt 2>nul set /a vw=!vw!+0 set /a vh=!vh!+0 set /a vbr=!vbr!+0 if "!vw!"=="!target_w!" if "!vh!"=="!target_h!" ( echo 当前分辨率已与目标一致,无需处理 pause & goto MENU ) set /a px=target_w - vw set /a px=px / 2 set /a py=target_h - vh set /a py=py / 2 echo 当前: !vw!(宽) x !vh!(高) 填充: 左右各!px!px 上下各!py!px echo 处理中... for /f "delims=" %%f in ("!vf!") do ( if "%SHOW_LOG%"=="1" ( ffmpeg -noautorotate -i "!vf!" -vf "pad=!target_w!:!target_h!:!px!:!py!:black" -c:v libx264 -preset fast -b:v !vbr! -video_track_timescale 90000 -c:a copy "%%~nf_padded%%~xf" -y ) else ( ffmpeg -noautorotate -i "!vf!" -vf "pad=!target_w!:!target_h!:!px!:!py!:black" -c:v libx264 -preset fast -b:v !vbr! -video_track_timescale 90000 -c:a copy "%%~nf_padded%%~xf" -y -loglevel error ) ) if !errorlevel! equ 0 ( echo 成功 ) else ( echo 失败 ) pause & goto MENU :: ========================================== :: 模式 8: 预处理视频参数 (对比并统一) :: ========================================== :MODE_PREPROCESS cls echo [模式: 预处理视频参数 - 对比并统一] echo. set /a file_count=0 set /a index=0 echo 序号 文件名 echo ---------------------------------------- for /f "delims=" %%i in ('dir /b *.mp4 *.mov *.m4v 2^>nul') do ( set "tn=%%i" echo !tn! | findstr /i "_handle" >nul if errorlevel 1 ( set /a index+=1 set "file_!index!=%%i" set /a file_count+=1 echo !index!. %%i ) ) if !file_count! equ 0 (echo 未找到视频文件 & pause & goto MENU) echo. set /p sel="输入要对比的文件序号(逗号分隔,至少2个): " if "%sel%"=="" goto MENU del temp_sel.txt 2>nul set "sel=%sel: =%" set "sel=%sel:,= %" for %%n in (%sel%) do ( call set "tmpf=%%file_%%n%%" echo !tmpf! >> temp_sel.txt ) :: 读取文件信息并存入变量 set /a maxw=0 set /a maxh=0 set /a sel_count=0 for /f "delims=" %%f in (temp_sel.txt) do ( set /a sel_count+=1 echo %%f > temp_cur.txt set /p cur_file=<temp_cur.txt del temp_cur.txt 2>nul set "sel_file_!sel_count!=!cur_file!" ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 "!cur_file!" > temp_w.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 "!cur_file!" > temp_h.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of csv=s=x:p=0 "!cur_file!" > temp_br.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=time_base -of csv=s=x:p=0 "!cur_file!" > temp_tb.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of csv=s=x:p=0 "!cur_file!" > temp_fps.txt 2>nul ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of csv=s=x:p=0 "!cur_file!" > temp_codec.txt 2>nul ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "!cur_file!" > temp_dur.txt 2>nul set /p fw=<temp_w.txt set /p fh=<temp_h.txt set /p fbr=<temp_br.txt set /p ftb=<temp_tb.txt set /p ffps=<temp_fps.txt set /p fcodec=<temp_codec.txt set /p fdur=<temp_dur.txt del temp_w.txt temp_h.txt temp_br.txt temp_tb.txt temp_fps.txt temp_codec.txt temp_dur.txt 2>nul set /a fw=!fw!+0 set /a fh=!fh!+0 set "sel_w_!sel_count!=!fw!" set "sel_h_!sel_count!=!fh!" set "sel_br_!sel_count!=!fbr!" set "sel_tb_!sel_count!=!ftb!" set "sel_fps_!sel_count!=!ffps!" set "sel_codec_!sel_count!=!fcodec!" set "sel_dur_!sel_count!=!fdur!" if !fw! gtr !maxw! set /a maxw=!fw! if !fh! gtr !maxh! set /a maxh=!fh! ) del temp_sel.txt 2>nul :: 展示对比结果 echo. echo ========================================== echo 对比结果 echo ========================================== for /L %%i in (1,1,%sel_count%) do ( echo. echo [%%i] !sel_file_%%i! echo 分辨率 : !sel_w_%%i! x !sel_h_%%i! echo time_base: !sel_tb_%%i! echo 帧率 : !sel_fps_%%i! echo 编码 : !sel_codec_%%i! echo 码率 : !sel_br_%%i! bps echo 时长 : !sel_dur_%%i! 秒 ) echo. echo ========================================== echo 统一参数 echo ========================================== echo 目标分辨率 : !maxw! x !maxh! echo 目标time_base: 1/90000 echo. echo 将对每个文件生成 _handle 文件 echo ========================================== echo. set /p confirm="确认处理? (y/n): " if /i not "%confirm%"=="y" goto MENU echo. for /L %%i in (1,1,%sel_count%) do ( echo !sel_file_%%i! > temp_cf.txt echo !sel_w_%%i! > temp_vw.txt echo !sel_h_%%i! > temp_vh.txt echo !sel_tb_%%i! > temp_vtb.txt echo !sel_br_%%i! > temp_vbr.txt set /p cur_file=<temp_cf.txt set /p vw=<temp_vw.txt set /p vh=<temp_vh.txt set /p vtb=<temp_vtb.txt set /p vbr=<temp_vbr.txt del temp_cf.txt temp_vw.txt temp_vh.txt temp_vtb.txt temp_vbr.txt 2>nul set /a vw=!vw!+0 set /a vh=!vh!+0 set /a vbr=!vbr!+0 echo [%%i] 处理: !cur_file! set "need_pad=1" if "!vw!"=="!maxw!" if "!vh!"=="!maxh!" set "need_pad=0" set "need_tb=1" echo !vtb! > temp_check.txt findstr /x "1/90000" temp_check.txt >nul 2>nul if not errorlevel 1 set "need_tb=0" del temp_check.txt 2>nul if "!need_pad!"=="1" ( echo 填充分辨率 + 统一time_base set /a px=maxw - vw set /a px=px / 2 set /a py=maxh - vh set /a py=py / 2 for /f "delims=" %%f in ("!cur_file!") do ( ffmpeg -noautorotate -i "!cur_file!" -vf "pad=!maxw!:!maxh!:!px!:!py!:black" -c:v libx264 -preset fast -b:v !vbr! -video_track_timescale 90000 -c:a copy "%%~nf_handle%%~xf" -y -loglevel error ) ) if "!need_pad!"=="0" if "!need_tb!"=="1" ( echo 统一time_base for /f "delims=" %%f in ("!cur_file!") do ( ffmpeg -i "!cur_file!" -c copy -video_track_timescale 90000 "%%~nf_handle%%~xf" -y -loglevel error ) ) if "!need_pad!"=="0" if "!need_tb!"=="0" ( echo 无需处理,参数已一致 for /f "delims=" %%f in ("!cur_file!") do ( copy "!cur_file!" "%%~nf_handle%%~xf" >nul ) ) for /f "delims=" %%f in ("!cur_file!") do ( if exist "%%~nf_handle%%~xf" ( echo 成功: %%~nf_handle%%~xf ) else ( echo 失败 ) ) echo. ) echo ========================================== echo 全部处理完成 echo 请使用模式3直接合并所有 _handle 文件 echo ========================================== pause & goto MENU背景手头有一批视频文件需要批量处理:掐头去尾、合并分集、统一分辨率。想做一个放在视频目录下就能双击运行的 .bat 工具箱,依赖 FFmpeg 和 ffprobe,无需安装额外环境。最终实现的功能菜单:1. 移除视频开头 (掐头) 2. 移除视频结尾 (去尾) 3. 合并多个视频 (直接合并) 4. 合并多个视频 (全自动统一参数后合并) 5. 旋转视频 - 快速 (仅修改标记) 6. 旋转视频 - 真实 (重新编码) 7. 预处理视频分辨率 (填充黑边) 8. 预处理视频参数 (对比并统一) 9. 退出经典错误一览❌ 错误1:-metadata:s:v rotate=-90 修改旋转无效现象: 执行后视频没有任何变化。原因: -metadata:s:v rotate=-90 只是修改元数据标记,很多播放器不识别,且参数值应为 270 而非 -90。正确做法::: 快速旋转(仅改标记,秒级完成) ffmpeg -i input.mp4 -map 0 -c copy -metadata:s:v:0 rotate=270 output.mp4 :: 真实旋转(重新编码,100%兼容) ffmpeg -i input.mp4 -vf "transpose=2" -c:v libx264 output.mp4transpose 参数对照:1 = 顺时针90°2 = 逆时针90°2,transpose=2 = 旋转180°❌ 错误2:-ss 参数位置错误导致截取不准现象: 指定去掉开头8秒,实际从第6秒开始截取;输出文件比原文件还大。原因: -ss 放在 -i 之后是输出侧裁剪,需要解码所有帧,精度低且文件结构复杂。:: ❌ 错误写法(输出侧裁剪) ffmpeg -i input.mp4 -ss 8 -c copy output.mp4 :: ✅ 正确写法(输入侧裁剪,快速且精确) ffmpeg -ss 8 -i input.mp4 -c copy output.mp4❌ 错误3:ffprobe 获取分辨率时 %%h 变量失效现象: 脚本显示 宽=500 高=%h,高度变成了字面字符串。原因: 在 for 循环中使用 tokens=1,2 delims=x 时,%%h 作为第二个 token 变量,在循环外或特定上下文中会失效。修复: 将宽和高分两次独立获取,并通过临时文件中转:ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 "input.mp4" > temp_w.txt ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 "input.mp4" > temp_h.txt set /p vw=<temp_w.txt set /p vh=<temp_h.txt del temp_w.txt temp_h.txt❌ 错误4:文件名含 [ ] 导致 for /f 解析失败现象: 文件名如 [001]-video.mp4,在 for /f ... in ('dir /b') 循环中调用 ffprobe 时,分辨率始终为空。原因: CMD 的 for 循环会将 [ ] 当作通配符处理。修复: 先将文件名写入临时文件,再用 set /p 读取:echo %%f > temp_cur.txt set /p cur_file=<temp_cur.txt del temp_cur.txt ffprobe ... "!cur_file!" > temp_w.txt❌ 错误5:set /a 浮点数截断导致1KB空文件现象: 去除结尾操作后,输出文件只有1KB。原因: 视频时长是浮点数(如 125.47 秒),set /a 只能处理整数,直接赋值会截断为 125,导致 -t 参数计算错误。修复: 使用 PowerShell 计算浮点数:ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "input.mp4" > temp_dur.txt set /p dur=<temp_dur.txt for /f %%b in ('powershell -command "[math]::Round([double]'!dur!' - %rmsec%, 3)"') do set keep=%%b ffmpeg -i "input.mp4" -t !keep! -c copy output.mp4❌ 错误6:if !var!==!var! 触发 CMD 解析崩溃现象: 整个 for 循环块进不去,连第一行 pause 也无法执行,直接闪退。原因: if !vw!==!maxw! 展开后形如 if 608==608,CMD 解析时将右侧紧贴 == 的 ! 误识别为三个等号,导致整个代码块预解析失败。:: ❌ 危险写法 if !vw!==!maxw! ... :: ✅ 正确写法(变量两边加引号) if "!vw!"=="!maxw!" ...CMD 铁律:if 比较变量时必须加引号。❌ 错误7:for /L 循环内 if...else 嵌套导致预解析崩溃现象: 同样是进不去循环,直接闪退。原因: CMD 对整个括号块进行预解析,循环内嵌套 if "%SHOW_LOG%"=="1" (...) else (...) 会导致括号层次解析失败。:: ❌ 危险写法 for /L %%i in (1,1,%count%) do ( if "%SHOW_LOG%"=="1" ( ffmpeg ... ) else ( ffmpeg ... -loglevel error ) ) :: ✅ 修复写法(去掉 else,拆成两个独立 if) for /L %%i in (1,1,%count%) do ( if "%SHOW_LOG%"=="1" ffmpeg ... if "%SHOW_LOG%"=="0" ffmpeg ... -loglevel error )❌ 错误8:set /a px=(!maxw! - !vw!) / 2 导致 for 块崩溃(最隐蔽)现象: 经历了错误6、7的修复后,循环依然闪退,连循环体第一行都进不去。根本原因(由 GPT 最终定位):for (...) do ( ... ) 本身是代码块,内部再出现 set /a px=(...) 的算术括号,叠加延迟变量 !var!,CMD 预解析阶段会将括号结构解析错,导致整个 for 块语法崩溃。这是 CMD 解析期(parse-time)崩溃,而非运行期错误,因此任何运行期的修复都无效。:: ❌ 致命写法(for块内的算术括号) set /a px=(!maxw! - !vw!) / 2 set /a py=(!maxh! - !vh!) / 2 :: ✅ 正确写法(去掉括号,set /a 内可直接用变量名) set /a px=maxw - vw set /a px=px / 2 set /a py=maxh - vh set /a py=py / 2set /a 中可以直接使用变量名,不需要 !变量!,且不能在 for 块内使用括号表达式。❌ 错误9:合并视频后 time_base 不一致导致时间轴异常现象: 两个视频合并后,播放到衔接点卡住;用 ffprobe 检查合并文件时长,发现远超两段视频之和(如应为7000秒,实际显示41000秒)。诊断:ffprobe -v error -show_entries stream=codec_name,start_time,time_base -of default=noprint_wrappers=1 "video1.mp4" ffprobe -v error -show_entries stream=codec_name,start_time,time_base -of default=noprint_wrappers=1 "video2.mp4"输出对比:video1: time_base=1/15360 video2: time_base=1/90000原因: time_base 不一致,流复制拼接时时间戳计算完全错乱。修复: 合并前统一 time_base 为标准值 1/90000(无需重新编码,仅修改容器信息):ffmpeg -i "video1.mp4" -c copy -video_track_timescale 90000 "video1_fixed.mp4"❌ 错误10:填充黑边后 time_base 被重置现象: 用 -c:v libx264 重编码填充黑边后,生成文件的 time_base 变为非标准值,再与其他文件合并时又出现时间轴问题。修复: 填充黑边时同步指定 time_base:ffmpeg -noautorotate -i "input.mp4" ^ -vf "pad=1920:1080:8:0:black" ^ -c:v libx264 -preset fast -b:v 1200000 ^ -video_track_timescale 90000 ^ -c:a copy "output.mp4"CMD 批处理避坑总结问题错误写法正确写法变量比较if !a!==!b!if "!a!"=="!b!"for块内if分支if (...) else (...)拆成两个独立 iffor块内算术set /a x=(!a! - !b!) / 2set /a x=a-b / set /a x=x/2含特殊字符文件名直接在for循环中使用先写临时文件再 set /p 读取浮点数计算set /a 直接赋值通过 PowerShell 计算编码问题chcp 65001 (UTF-8)chcp 936 (ANSI/GBK)CMD 的 for 代码块会整体预解析,任何括号结构错误都会导致整块失效,表现为直接闪退。这是 parse-time 崩溃,与运行期错误性质不同,运行期的修复对其无效。FFmpeg 常用参数备忘:: 查看视频信息 ffprobe -v error -show_entries stream=codec_name,width,height,r_frame_rate,bit_rate,time_base -of default=noprint_wrappers=1 "input.mp4" :: 流复制截取(快速,输入侧 -ss) ffmpeg -ss 10 -i "input.mp4" -c copy "output.mp4" :: 填充黑边 ffmpeg -i "input.mp4" -vf "pad=宽:高:x偏移:y偏移:black" -c:v libx264 "output.mp4" :: 统一 time_base(不重编码) ffmpeg -i "input.mp4" -c copy -video_track_timescale 90000 "output.mp4" :: concat 合并 ffmpeg -f concat -safe 0 -i filelist.txt -c copy "output.mp4"工具依赖:FFmpeg(含 ffprobe),需加入系统 PATH。脚本放于视频目录下双击运行。
2026年04月29日
5 阅读
0 评论
0 点赞
2026-04-27
此内容被密码保护
加密文章,请前往内页查看详情
2026年04月27日
6 阅读
0 评论
0 点赞
2025-12-06
高中文科数学知识体系
🌟 高考文科数学知识体系总览(四大主干 + 两大工具)主干模块核心内容分值占比(约)1. 函数与导数函数性质、图像、基本初等函数、导数及其应用20%~25%2. 数列等差/等比数列、通项公式、求和、简单递推10%~15%3. 三角函数与解三角形三角恒等变换、图像性质、正余弦定理10%~15%4. 概率与统计抽样方法、频率分布、古典概型、回归分析、独立性检验15%~20%工具支撑立体几何(空间想象)、平面解析几何(直线、圆、椭圆)各占8%~12%✅ 文科不考:复数运算(仅概念)、排列组合(仅极简)、二项式定理、空间向量、参数方程、极坐标、不等式证明等理科内容。一、函数与导数(核心中的核心)1. 函数基础定义域、值域、对应关系单调性、奇偶性、周期性分段函数、复合函数2. 基本初等函数一次、二次函数(顶点、对称轴、最值)指数函数 ( y = a^x )((a>0, aneq1))对数函数 ( y = log_a x )(与指数互为反函数)幂函数 ( y = x^alpha )(常见 (alpha = -1, frac{1}{2}, 2, 3))3. 函数图像与变换平移、对称、伸缩零点存在性定理(图像与x轴交点)4. 导数(文科要求较低,但必考!)导数定义(几何意义:切线斜率)基本求导公式(常数、幂函数、和差积商)利用导数判断单调性、求极值/最值(应用题如利润最大、成本最小)📌 高频题型:含参函数单调性讨论、实际问题建模(如利润、面积最大)二、数列1. 等差数列通项:( a_n = a_1 + (n-1)d )求和:( S_n = frac{n(a_1 + a_n)}{2} )2. 等比数列通项:( a_n = a_1 q^{n-1} )求和:( S_n = a_1 frac{1 - q^n}{1 - q} )((q ne 1))3. 数列综合简单递推(如 ( a_{n+1} = a_n + d ) 或 ( a_{n+1} = q a_n ))数列与函数、不等式结合(较少,难度低)📌 文科几乎不考错位相减、裂项相消等复杂技巧,重点在识别模型+套公式。三、三角函数与解三角形1. 三角恒等变换同角关系:( sin^2 x + cos^2 x = 1 )诱导公式(“奇变偶不变,符号看象限”)和差角公式(文科只需记住 (sin(Apm B), cos(Apm B)))二倍角公式((sin 2x = 2sin x cos x) 等)2. 三角函数图像与性质( y = Asin(omega x + varphi) + k ) 的振幅、周期、相位、最值单调区间、对称轴/中心3. 解三角形(正弦定理 & 余弦定理)正弦定理:( frac{a}{sin A} = frac{b}{sin B} = frac{c}{sin C} = 2R )余弦定理:( c^2 = a^2 + b^2 - 2abcos C )实际应用:测量高度、距离等📌 高频题型:给边角关系求角/边,或判断三角形形状。四、概率与统计(文科重点,易得分!)1. 随机抽样简单随机抽样、系统抽样、分层抽样(会判断、会计算样本量)2. 用样本估计总体频率分布直方图(会读图、算平均数、中位数、众数)茎叶图、折线图3. 概率古典概型(列举法、树状图)几何概型(长度、面积比,较少考)4. 统计案例(必考大题!)线性回归分析(最小二乘法公式,会代入计算)独立性检验(卡方公式 ( K^2 = frac{n(ad-bc)^2}{(a+b)(c+d)(a+c)(b+d)} ),查表判断)📌 大题常考:给出数据 → 画图/计算回归方程 → 预测 → 独立性检验。五、立体几何(空间想象)三视图(主视、俯视、左视 → 还原几何体)常见几何体:柱、锥、台、球的表面积与体积点线面位置关系(平行、垂直的判定与性质)文科不要求空间向量法,用几何法证明即可(如线面平行→找中位线)📌 小题考三视图或体积;大题考平行/垂直证明 + 体积计算。六、平面解析几何1. 直线与圆直线方程(点斜式、一般式)两直线位置关系(平行、垂直条件)圆的标准方程 ( (x-a)^2 + (y-b)^2 = r^2 )直线与圆的位置关系(距离 vs 半径)2. 圆锥曲线(文科只考椭圆!)椭圆标准方程:( frac{x^2}{a^2} + frac{y^2}{b^2} = 1 )((a > b > 0))几何性质:焦点、焦距、离心率 ( e = frac{c}{a} )不考双曲线、抛物线的复杂性质📌 椭圆题多为基础题:给方程求焦点、离心率,或简单联立直线。🔚 总结:文科数学“三抓三放”✅ 抓基础:公式、图像、定义必须滚瓜烂熟 ✅ 抓高频:函数、概率统计、数列、三角是提分关键 ✅ 抓规范:大题步骤分严格,书写要清晰 ❌ 放难题:不纠结偏题、怪题、超纲题 ❌ 放技巧:不追求秒杀,重通法通解 ❌ 放焦虑:文科数学重应用、轻理论,稳扎稳打可拿高分!
2025年12月06日
68 阅读
0 评论
0 点赞
2025-08-27
解决Docker容器中MySQL连接因LANG环境变量缺失导致的问题
解决Docker容器中MySQL连接因LANG环境变量缺失导致的问题问题描述在使用Docker容器部署Spring Boot应用时,遇到以下错误:java.lang.IllegalStateException: DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect环境信息:Docker容器:基于Ubuntu 22.04,运行宝塔面板数据库:MySQL 8.0.26(独立容器)应用:Spring Boot + Logback + MySQL Connector 8.0.16关键发现:同样的JAR包在虚拟机上运行正常,在容器中无法启动快速解决方案根本解决方案(推荐):apt-get update && apt-get install -y locales && locale-gen en_US.UTF-8 && update-locale LANG=en_US.UTF-8 && export LANG=en_US.UTF-8 && export LC_ALL=en_US.UTF-8 && echo 'export LANG=en_US.UTF-8' >> ~/.bashrc && echo 'export LC_ALL=en_US.UTF-8' >> ~/.bashrc && source ~/.bashrc临时解决方案(连接参数):在数据库连接URL中添加:allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8spring: datasource: url: jdbc:mysql://127.0.0.1:3306/your_database?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8或者在启动容器时添加环境变量:docker run -d \ --name your-container \ --net=host \ --restart always \ --privileged \ -e LANG=C.UTF-8 \ -e LC_ALL=C.UTF-8 \ your-image:tag详细排查过程初期错误理解最初看到错误信息,以为是Logback配置问题,尝试了多种方案:取消注释SQL方言配置 ❌<sqlDialect class="ch.qos.logback.core.db.dialect.MySQLDialect"/>使用DriverManagerConnectionSource ❌升级/降级Logback版本 ❌使用HikariCP替代Commons DBCP ❌暂时禁用DBAppender ✅(临时方案,不是根本解决)转换思路:环境差异分析经过两天的配置调试无果后,开始从环境角度分析问题。1. Java版本对比# 容器和虚拟机都是相同版本 java version "1.8.0_381" Java(TM) SE Runtime Environment (build 1.8.0_381-b09)2. 环境变量对比容器环境:JAVA_HOME=/home/root/soft/jdk1.8.0_381 PATH=/home/root/soft/jdk1.8.0_381/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin # 缺失 LANG 和 LC_* 变量虚拟机环境:JAVA_HOME=/home/root/soft/jdk1.8.0_381 LANG=en_US.UTF-8 # 关键差异! PATH=/home/root/soft/jdk1.8.0_381/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin3. MySQL驱动行为测试创建测试程序验证MySQL驱动的getGeneratedKeys支持:import java.sql.*; public class TestMySQLDriver { public static void main(String[] args) { try { Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn = DriverManager.getConnection( "jdbc:mysql://127.0.0.1:3306/your_database?useSSL=false", "username", "password"); DatabaseMetaData meta = conn.getMetaData(); System.out.println("supportsGetGeneratedKeys: " + meta.supportsGetGeneratedKeys()); System.out.println("Driver version: " + meta.getDriverVersion()); System.out.println("Database version: " + meta.getDatabaseProductVersion()); conn.close(); } catch (Exception e) { e.printStackTrace(); } } }测试结果对比:容器中:java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835) ... at TestMySQLDriver.main(TestMySQLDriver.java:7)虚拟机中:supportsGetGeneratedKeys: true Driver version: mysql-connector-java-8.0.16 Database version: 8.0.26关键发现: 容器环境尝试设置LANG环境变量时出现警告:export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 -bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)根因分析核心问题: 容器环境缺少LANG和LC_ALL环境变量,导致:Public Key Retrieval错误 - 这是MySQL 8.0的安全特性,在字符编码异常时更容易触发字符编码处理异常 - MySQL连接器在处理字符编码时出现问题SSL/TLS握手失败 - 编码问题影响了安全连接的建立getGeneratedKeys方法识别失败 - 驱动无法正确识别数据库功能支持本质问题: Public Key Retrieval is not allowed 错误在MySQL 8.0中很常见,但通常在环境正常的情况下可以通过连接参数解决。然而在缺少locale的容器环境中,这个错误变得更加顽固。解决方案详解方案1:修复LANG环境变量(根本解决方案,推荐)# 1. 安装locale支持 apt-get update apt-get install -y locales # 2. 生成UTF-8 locale locale-gen en_US.UTF-8 update-locale LANG=en_US.UTF-8 # 3. 设置环境变量 export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 # 4. 永久化配置 echo 'export LANG=en_US.UTF-8' >> ~/.bashrc echo 'export LC_ALL=en_US.UTF-8' >> ~/.bashrc source ~/.bashrc # 5. 验证配置 locale方案2:连接字符串参数解决(临时方案)如果无法修改容器环境,可以通过调整MySQL连接参数来绕过这个问题:// 添加 allowPublicKeyRetrieval=true 参数 String url = "jdbc:mysql://127.0.0.1:3306/your_database?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8";完整连接参数建议:String url = "jdbc:mysql://127.0.0.1:3306/your_database?" + "useSSL=false&" + "allowPublicKeyRetrieval=true&" + "useUnicode=true&" + "characterEncoding=UTF-8&" + "serverTimezone=Asia/Shanghai";Spring Boot配置文件:spring: datasource: url: jdbc:mysql://127.0.0.1:3306/your_database?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: username password: password driver-class-name: com.mysql.cj.jdbc.Driver注意: 方案2虽然能解决连接问题,但不能根本解决locale缺失问题,可能在其他功能上仍有隐患。推荐优先使用方案1。方案3:Docker启动时配置docker run -d \ --name baota \ --net=host \ --restart always \ --privileged \ -e LANG=C.UTF-8 \ -e LC_ALL=C.UTF-8 \ -v /path/to/data:/data \ your-image:tag方案4:Dockerfile中预设FROM ubuntu:22.04 # 安装locale并设置环境变量 RUN apt-get update && \ apt-get install -y locales && \ locale-gen en_US.UTF-8 && \ update-locale LANG=en_US.UTF-8 ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 # 其他配置...验证解决效果修复后重新测试MySQL连接:java -cp .:mysql-connector-java-8.0.16.jar TestMySQLDriver期望输出:supportsGetGeneratedKeys: true Driver version: mysql-connector-java-8.0.16 Database version: 8.0.26经验总结环境一致性的重要性 - 看似相同的环境可能存在关键差异字符编码的影响范围 - LANG环境变量不仅影响显示,还会影响网络通信和数据库连接问题定位思路 - 当配置层面无法解决时,要从环境层面分析Docker容器的注意事项 - 容器环境通常是精简的,可能缺少一些基础的系统配置相关问题和预防类似问题可能出现在:其他需要字符编码的Java应用Python应用的数据库连接文件上传/下载功能国际化(i18n)应用预防措施:构建Docker镜像时主动设置LANG环境变量在CI/CD流程中添加环境一致性检查制作标准化的基础镜像,包含必要的locale配置关键要点:根本问题是locale缺失:Public Key Retrieval is not allowed 在MySQL 8.0中很常见,但在locale正常的环境中通常可以通过连接参数解决。在Docker容器的精简环境中,locale缺失使这个问题变得更加复杂。两种解决思路:治本:修复容器的locale环境,这样应用的各个方面都能正常工作治标:通过连接参数绕过验证,但可能在其他功能上仍有隐患环境一致性:Docker容器环境的精简性可能导致一些看似无关的系统配置缺失,而这些配置对应用的正常运行至关重要。在排查此类问题时,环境差异分析往往比配置调优更有效。
2025年08月27日
64 阅读
0 评论
0 点赞
2025-07-14
uni.getSystemInfoSync 全量信息解析
📱 uni.getSystemInfoSync 全量信息解析(iPhone 12 + iOS 18.5 示例)在开发基于 UniApp 的移动应用时,获取设备信息对于 UI 适配、安全区域计算、调试优化 至关重要。本文将基于一份真实的系统信息(以 iPhone 12 为例),完整解析 uni.getSystemInfoSync() 返回的数据结构,并提供适配建议。注:所有敏感信息如设备ID、AppID 等均已脱敏或替换。📦 基础信息字段示例值含义brand / deviceBrandapple设备品牌model / deviceModeliPhone 12设备型号platformios系统平台system / osVersioniOS 18.5系统版本language / osLanguagezh-Hans-HK当前系统语言(简体中文-香港)deviceTypephone设备类型📐 屏幕 & 像素信息字段示例值含义pixelRatio / devicePixelRatio3物理像素 / 逻辑像素比screenWidth390 px屏幕宽度screenHeight844 px屏幕高度windowWidth390 px可视区域宽度windowHeight844 px可视区域高度statusBarHeight47 px状态栏高度(刘海高度)🔒 安全区域信息安全区域对于适配刘海屏和底部 Home Indicator 非常重要。"safeArea": { "top": 47, "bottom": 810, "left": 0, "right": 390, "width": 390, "height": 763 }, "safeAreaInsets": { "top": 47, "bottom": 34, "left": 0, "right": 0 }字段示例值含义safeAreaInsets.top47 px顶部安全区(通常是状态栏)safeAreaInsets.bottom34 px底部安全区(通常是 Home Indicator 区域)safeArea.height763 px内容区高度(去除安全边距)🧱 App & UniApp 信息字段示例值含义appNameMyApp应用名称(已脱敏)appId__UNI__xxxxxxx应用 ID(已脱敏)appVersion14.75用户可见版本appVersionCode1475内部版本号(用于版本比较)appWgtVersion4.3.54资源版本(wgt 包)uniPlatformapp当前平台uniCompileVersion4.64编译时使用的 HBuilderX 版本uniRuntimeVersion4.75App 运行时版本browserNamewkwebviewiOS 内核类型browserVersion18.5WebView 版本(与系统一致)uaMozilla/5.0...uni-app浏览器 UserAgent(已截断)🧪 实际使用建议✅ 状态栏高度使用:padding-top: var(--status-bar-height); // 适配刘海屏✅ Bottom 安全区适配:padding-bottom: env(safe-area-inset-bottom); // 适配 Home Indicator✅ JS 动态计算 padding:const system = uni.getSystemInfoSync(); const paddingTop = system.statusBarHeight + 44; // 状态栏 + 自定义导航栏 const paddingBottom = system.safeAreaInsets.bottom + 55; // Home Indicator + 底部 tab🎯 调试辅助(推荐实践)在开发过程中你可以引入一个 浮动调试按钮,点击后显示当前系统信息及安全区计算值,便于测试不同设备的实际效果。例如:minHeight: 100vhpaddingTop: calc(var(--status-bar-height) + 44px)paddingBottom: calc(env(safe-area-inset-bottom) + 55px)🧾 总结本文详细解析了 uni.getSystemInfoSync() 的所有关键字段及含义,尤其针对 iPhone 12 的刘海屏、安全区域、底部指示器做了说明。了解这些参数,可以帮助我们开发时更好地进行:UI 适配页面布局计算自定义导航栏和底部栏浮动调试工具实现
2025年07月14日
69 阅读
0 评论
0 点赞
1
2
...
77
您的IP: