-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
hojas
committed
May 8, 2024
1 parent
09ec33e
commit 80fc1ff
Showing
8 changed files
with
284 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
title: 博客文章 | ||
--- | ||
|
||
# 博客文章 | ||
|
||
1. [使用 Docker 一键部署带 Let's Encrypt SSL 证书的 Nginx](./blog/1.md) | ||
2. [使用 Vue 实现音频可视化](./blog/2.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
--- | ||
title: 使用 Docker 一键部署带 Let's Encrypt SSL 证书的 Nginx | ||
--- | ||
|
||
# 使用 Docker 一键部署带 Let's Encrypt SSL 证书的 Nginx | ||
|
||
使用镜像 [nginx-proxy](https://github.com/nginx-proxy/nginx-proxy) 和 [acme-companion](https://github.com/nginx-proxy/acme-companion) 可以很方便地一键部署带 Let's Encrypt SSL 证书的 Nginx。 | ||
|
||
nginx-proxy 设置了一个运行 nginx 和 docker-gen 的容器。docker-gen 为 nginx 生成反向代理配置,并在容器启动和停止时重新加载 nginx。 | ||
|
||
acme-companion 是 nginx-proxy 的轻量级配套容器。它通过 ACME 协议为代理的 Docker 容器自动创建、更新和使用 SSL 证书。 | ||
|
||
编写一键部署的 `docker-compose.yaml` 文件: | ||
|
||
```yaml | ||
services: | ||
nginx-proxy: | ||
container_name: nginx-proxy | ||
image: nginxproxy/nginx-proxy:alpine | ||
restart: always | ||
ports: | ||
- 80:80 | ||
- 443:443 | ||
volumes: | ||
- conf:/etc/nginx/conf.d | ||
- vhost:/etc/nginx/vhost.d | ||
- html:/usr/share/nginx/html | ||
- certs:/etc/nginx/certs:ro | ||
- /var/run/docker.sock:/tmp/docker.sock:ro | ||
networks: | ||
- nginx-proxy | ||
acme-companion: | ||
container_name: nginx-proxy-acme | ||
image: nginxproxy/acme-companion | ||
restart: always | ||
environment: | ||
- [email protected] | ||
volumes_from: | ||
- nginx-proxy | ||
volumes: | ||
- certs:/etc/nginx/certs:rw | ||
- acme:/etc/acme.sh | ||
- /var/run/docker.sock:/var/run/docker.sock:ro | ||
networks: | ||
- nginx-proxy | ||
|
||
networks: | ||
nginx-proxy: | ||
driver: bridge | ||
name: nginx-proxy | ||
|
||
volumes: | ||
conf: | ||
vhost: | ||
html: | ||
certs: | ||
acme: | ||
``` | ||
然后启动 Docker 容器: | ||
```bash | ||
$ docker compose up -d | ||
``` | ||
|
||
在需要部署的应用中添加环境变量相关变量,并指定相关网络,例如: | ||
|
||
```yaml | ||
services: | ||
web: | ||
container_name: web | ||
image: node:20-alpine | ||
restart: always | ||
environment: | ||
- LETSENCRYPT_HOST=example.com | ||
- VIRTUAL_HOST=example.com | ||
- VIRTUAL_PORT=3000 | ||
- VIRTUAL_PATH=/ | ||
networks: | ||
- nginx-proxy | ||
|
||
networks: | ||
nginx-proxy: | ||
external: true | ||
``` | ||
然后启动应用容器: | ||
```bash | ||
$ docker compose up -d | ||
``` | ||
|
||
这样就可以在 `example.com` 上访问到部署的应用,并且自动配置了 Let's Encrypt SSL 证书。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
--- | ||
title: 用 Vue 实现音频可视化 | ||
--- | ||
|
||
# 用 Vue 实现音频可视化 | ||
|
||
使用 `Web Audio API` 和 canvas 实现音频可视化。 | ||
|
||
https://developer.mozilla.org/en-US/docs/Web/API/AudioContext | ||
|
||
## 效果 | ||
|
||
<script setup> | ||
import VoiceVisualization from './voice-visualization/voice-visualization.vue' | ||
</script> | ||
|
||
<VoiceVisualization audio-source="./voice-visualization/Immortal.mp3" /> | ||
|
||
## 代码 | ||
|
||
```vue | ||
<script setup> | ||
import { onBeforeUnmount, onMounted, ref } from 'vue' | ||
defineProps({ | ||
audioSource: { | ||
type: String, | ||
required: true, | ||
}, | ||
}) | ||
// 音频元素 | ||
const audio = ref() | ||
// 画布元素 | ||
const canvas = ref() | ||
// 画布上下文 | ||
const ctx = ref() | ||
// 音频分析节点 | ||
const analyser = ref() | ||
// 音频分析数据 | ||
const dataArray = ref() | ||
const animationId = ref() | ||
/** | ||
* 初始化画布 | ||
*/ | ||
function initCanvas() { | ||
if (ctx.value) | ||
return | ||
// 获取画布 | ||
canvas.value = canvas.value || canvas.value.$refs.canvas | ||
// 获取画布上下文 | ||
ctx.value = canvas.value.getContext('2d') | ||
ctx.value.fillRect(0, 0, canvas.value.width, canvas.value.height) | ||
} | ||
/** | ||
* 音频播放事件 | ||
*/ | ||
function onAudioPlay() { | ||
// 音频上下文 | ||
const audioCtx = new AudioContext() | ||
// 音频源节点 | ||
const source = audioCtx.createMediaElementSource(audio.value) | ||
// 音频分析节点 | ||
analyser.value = audioCtx.createAnalyser() | ||
// 音频输出节点 | ||
const destination = audioCtx.destination | ||
analyser.value.fftSize = 512 | ||
// 创建数组,用于接收分析器节点的分析数据 | ||
// analyser.frequencyBinCount = analyser.fftSize / 2 | ||
// 为什么用Uint8Array? | ||
// 因为音频分析数据是无符号整数,范围是0~255 | ||
// Uint8Array的范围也是0~255,所以可以直接使用 | ||
// 可以用普通数组吗? | ||
// 可以,但是需要将数据转换为无符号整数 | ||
dataArray.value = new Uint8Array(analyser.value.frequencyBinCount) | ||
source.connect(analyser.value) | ||
analyser.value.connect(destination) | ||
} | ||
/** | ||
* 绘制音频图 | ||
*/ | ||
function draw() { | ||
// 递归调用 | ||
animationId.value = requestAnimationFrame(draw) | ||
// 如果没有音频分析节点,不绘制 | ||
if (!analyser.value) | ||
return | ||
const width = canvas.value.width | ||
const height = canvas.value.height | ||
// 清空画布 | ||
ctx.value.clearRect(0, 0, width, height) | ||
// 获取音频分析数据 | ||
analyser.value.getByteFrequencyData(dataArray.value) | ||
// 除以2.5是为了让音频图更加平滑 | ||
const len = dataArray.value.length / 2.5 | ||
const barWidth = width / len / 2 | ||
ctx.value.fillStyle = '#99f' | ||
for (let i = 0; i < len; i++) { | ||
const data = dataArray.value[i] | ||
// 除以255是为了让音频图的高度不超过画布高度 | ||
const barHeight = data / 255 * height | ||
const x1 = barWidth * i + width / 2 | ||
const x2 = width / 2 - barWidth * (i + 1) | ||
const y = height - barHeight | ||
// 绘制两个对称的图形 | ||
// 宽度减2,留出间隙 | ||
// 右边的图形 | ||
ctx.value.fillRect(x1, y, barWidth - 2, barHeight) | ||
// 左边的图形 | ||
ctx.value.fillRect(x2, y, barWidth - 2, barHeight) | ||
} | ||
} | ||
onMounted(() => { | ||
initCanvas() | ||
draw() | ||
audio.value.addEventListener('play', onAudioPlay) | ||
}) | ||
onBeforeUnmount(() => { | ||
cancelAnimationFrame(animationId.value) | ||
audio.value.removeEventListener('play', onAudioPlay) | ||
}) | ||
</script> | ||
<template> | ||
<div class="voice-visualization"> | ||
<div class="canvas-container"> | ||
<canvas ref="canvas" /> | ||
</div> | ||
<div class="audio-container"> | ||
<audio ref="audio" controls> | ||
<source :src="audioSource" type="audio/mpeg"> | ||
</audio> | ||
</div> | ||
</div> | ||
</template> | ||
<style scoped> | ||
.voice-visualization { | ||
padding: 20px 0; | ||
} | ||
canvas { | ||
width: 100%; | ||
height: 300px; | ||
} | ||
.canvas-container { | ||
border: solid 1px #eee; | ||
} | ||
.audio-container { | ||
display: flex; | ||
justify-content: center; | ||
margin-top: 20px; | ||
} | ||
</style> | ||
``` |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters