所以我正在编写一个 bash 脚本来生成带有视频文件链接的 html 页面,但我遇到了一个绊脚石。我希望能够按日期添加视频链接,以最大限度地减少每页的链接数量,然后有一个索引页面,其中包含指向可用日期以及当天有多少视频可用的链接。这是为了允许使用 lighttpd 轻松访问由树莓派上的网络摄像头设置的运动创建的视频文件,因此需要简单地减少 pi 上的负载。我会在清晨用 cron 运行 bash 脚本,那时不会录制视频。
如果有人有兴趣做同样的事情,我会将完成的脚本添加到 github/gitlab 并将其链接回此页面
索引页
01/04/2024 - 10 videos
02/04/2024 - 20 videos
etc...
以及每天页面
thumbnail - time - length - download link
这是我到目前为止能够破解的,它生成缩略图但无法生成 html 页面。
./test2.sh: line 128: 2024-03-25.html: command not found
./test2.sh: line 128: : No such file or directory
视频的文件名格式为 (yyyy-mm-dd-hh-mm-ss) 忽略 html 代码,因为当我让其余代码工作时我将更改它,并且有一些回声需要检查一旦我完成测试,数组的内容将从脚本中删除。
#!/bin/sh
set -e
script_dir=$(dirname "$(readlink -f "$0")")
cd "$script_dir" || exit
#list of directories
videos_dir="/home/allan/Documents/videos/"
thumbs_dir="/home/allan/Documents/thumbnails/"
mkdir -p "$videos_dir"
mkdir -p "$thumbs_dir"
#Declare arrays
parts=()
combine=()
args=()
uniq=()
# Loop over all video files.
for video_file in "$videos_dir"/*; do
video_name="$(basename "${video_file}")"
thumb_name="$(basename "${video_file%.*}.jpg")"
thumb_file="$thumbs_dir/$thumb_name"
# If thumnail doesn't exist for this video.
if [ ! -e "$thumb_file" ]; then
printf "generating thumbnail: %s\n" "$thumb_name"
ffmpeg -loglevel error -i "$video_file" -vf "thumbnail,scale=320:240" -frames:v 1 "$thumb_file"
fi
parts=(${video_name//-/ })
combine=(${parts[0]}-${parts[1]}-${parts[2]})
args+=("$combine")
# Generate html for each item.
items_html="$items_html""
<div class='grid-item-container'>
<img class='grid-item' src='${thumb_file}' data='${video_file}'/>
<div class='player-top-bar'>
<span class='player-top-bar-text'>$video_name</span>
</div>
</div>"
done
echo "${args[@]}"
uniq=($(printf "%s\n" "${args[@]}" | sort -u)); echo "${uniq[@]}"
for day in "${uniq[@]}"; do
# Write html page for each day with videos
echo "
<html lang='en'>
<head>
<title>Video Viewer</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
<div style='display:grid; grid-template-columns:repeat(var(--gridsize), auto)'>
$items_html
</div>
</body>
<script>
document.querySelector('body').addEventListener('click', (event) => {
const element = event.target;
if (element.className !== 'grid-item') {
return;
}
const videoPath = element.getAttribute('data');
const videoElement = document.createElement('video');
videoElement.className = 'grid-item'
videoElement.setAttribute('controls', '')
videoElement.setAttribute('autoplay', '')
videoElement.setAttribute('data', element.src)
const sourceElement = document.createElement('source');
sourceElement.src = videoPath
videoElement.appendChild(sourceElement)
element.parentNode.replaceChild(videoElement, element);
});
</script>
<style>
.grid-item-container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
max-height: 100vh;
}
.grid-item {
width: 100%;
height: 100%;
}
.player-top-bar {
display: flex;
flex-wrap: wrap;
opacity: 0.8;
position: absolute;
top: 0;
left: 0;
}
.player-top-bar-text {
padding: 0.05em 0.4em 0.05em 0.2em;
color: hsl(215deg, 40%, 90%);;
font-size: 40%;
background: hsl(215deg, 40%, 8%);
}
:root {
font-size: 12vw; /* Window scale */
--gridsize: 1;
}
/* Tablet/Dektop. */
@media only screen and (min-width: 768px) {
:root {
font-size: 4.5vh; /* Window scale. */
--gridsize: 3;
}
}
</style>" > "$("${day}.html")" ;
done
错误消息提到第 128 行。这是第 128 行:
</style>" > "$("${day}.html")" ;
错误消息还提到了
2024-03-25.html: command not found
。换句话说,bash
正在尝试将 2024-03-25.html
作为命令运行。
这一切都与之前的评论有关:你认为
"$("${day}.html")"
意味着什么?
构造
$( .... )
调用一个子shell来执行括号之间的任何内容。假设 day=2024-03-25
这意味着你的代码变成:
$(2024-03-25.html)
由于
2024-03-25.html
在您的环境中可能不是有效的二进制文件、脚本、函数或别名,因此您会收到错误消息。
由于这部分脚本的目标是将 76 行静态 html 代码写入文件,因此无需调用子 shell 来指定文件名。
简单的修复:
#### replace this:
</style>" > "$("${day}.html")" ;
#### with this:
</style>" > "${day}.html"
注意:在这种情况下,尾随的
;
是多余的