Spaces:
Sleeping
Sleeping
Upload 964 files (#1)
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +23 -0
- .github/workflows/docker.yml +66 -0
- .github/workflows/publish.yml +17 -0
- .github/workflows/update.yml +47 -0
- .github/workflows/update_poetry_lock.yml +32 -0
- .gitignore +10 -0
- .pre-commit-config.yaml +26 -0
- Dockerfile +49 -0
- LICENSE +21 -0
- docker/config.toml.template +19 -0
- docker/start.sh +7 -0
- docs/develop.md +135 -0
- docs/docker.md +56 -0
- docs/examples/avatar.jpg +0 -0
- docs/examples/test_api.py +23 -0
- docs/examples/test_meme.py +16 -0
- docs/images/5000choyen.jpg +0 -0
- docs/images/acg_entrance.jpg +0 -0
- docs/images/add_chaos.jpg +0 -0
- docs/images/addiction.jpg +0 -0
- docs/images/alike.jpg +0 -0
- docs/images/always.jpg +0 -0
- docs/images/always_instance0.jpg +0 -0
- docs/images/always_instance1.jpg +0 -0
- docs/images/always_instance2.gif +0 -0
- docs/images/always_like.jpg +0 -0
- docs/images/anti_kidnap.jpg +0 -0
- docs/images/anya_suki.jpg +0 -0
- docs/images/applaud.gif +0 -0
- docs/images/ascension.jpg +0 -0
- docs/images/ask.png +0 -0
- docs/images/back_to_work.jpg +0 -0
- docs/images/bad_news.png +0 -0
- docs/images/beat_head.gif +0 -0
- docs/images/bite.gif +0 -0
- docs/images/blood_pressure.jpg +0 -0
- docs/images/bocchi_draft.gif +3 -0
- docs/images/bronya_holdsign.jpg +0 -0
- docs/images/bubble_tea.jpg +0 -0
- docs/images/bubble_tea_instance0.jpg +0 -0
- docs/images/bubble_tea_instance1.jpg +0 -0
- docs/images/bubble_tea_instance2.jpg +0 -0
- docs/images/call_110.jpg +0 -0
- docs/images/caoshen_bite.gif +3 -0
- docs/images/capoo_draw.gif +0 -0
- docs/images/capoo_rip.gif +0 -0
- docs/images/capoo_rub.gif +0 -0
- docs/images/capoo_say.gif +0 -0
- docs/images/capoo_strike.gif +0 -0
- docs/images/captain.jpg +0 -0
.gitattributes
CHANGED
@@ -33,3 +33,26 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
docs/images/bocchi_draft.gif filter=lfs diff=lfs merge=lfs -text
|
37 |
+
docs/images/caoshen_bite.gif filter=lfs diff=lfs merge=lfs -text
|
38 |
+
docs/images/confuse.gif filter=lfs diff=lfs merge=lfs -text
|
39 |
+
docs/images/karyl_point.png filter=lfs diff=lfs merge=lfs -text
|
40 |
+
docs/images/kirby_hammer_instance0.gif filter=lfs diff=lfs merge=lfs -text
|
41 |
+
docs/images/kirby_hammer_instance1.gif filter=lfs diff=lfs merge=lfs -text
|
42 |
+
docs/images/kirby_hammer.gif filter=lfs diff=lfs merge=lfs -text
|
43 |
+
meme_generator/memes/anti_kidnap/images/0.png filter=lfs diff=lfs merge=lfs -text
|
44 |
+
meme_generator/memes/dinosaur/images/0.png filter=lfs diff=lfs merge=lfs -text
|
45 |
+
meme_generator/memes/dog_of_vtb/images/0.png filter=lfs diff=lfs merge=lfs -text
|
46 |
+
meme_generator/memes/gif_subtitle/images/maikease.gif filter=lfs diff=lfs merge=lfs -text
|
47 |
+
meme_generator/memes/gif_subtitle/images/qiegewala.gif filter=lfs diff=lfs merge=lfs -text
|
48 |
+
meme_generator/memes/gif_subtitle/images/shuifandui.gif filter=lfs diff=lfs merge=lfs -text
|
49 |
+
meme_generator/memes/gif_subtitle/images/wangjingze.gif filter=lfs diff=lfs merge=lfs -text
|
50 |
+
meme_generator/memes/gif_subtitle/images/weisuoyuwei.gif filter=lfs diff=lfs merge=lfs -text
|
51 |
+
meme_generator/memes/mourning/images/0.png filter=lfs diff=lfs merge=lfs -text
|
52 |
+
resources/fonts/FZKATJW.ttf filter=lfs diff=lfs merge=lfs -text
|
53 |
+
resources/fonts/FZSEJW.ttf filter=lfs diff=lfs merge=lfs -text
|
54 |
+
resources/fonts/FZSJ-QINGCRJ.ttf filter=lfs diff=lfs merge=lfs -text
|
55 |
+
resources/fonts/FZXS14.ttf filter=lfs diff=lfs merge=lfs -text
|
56 |
+
resources/fonts/HiraginoMin-W5-90-RKSJ-H-2.ttc filter=lfs diff=lfs merge=lfs -text
|
57 |
+
resources/fonts/NotoSansSC-Regular.otf filter=lfs diff=lfs merge=lfs -text
|
58 |
+
resources/fonts/NotoSerifSC-Regular.otf filter=lfs diff=lfs merge=lfs -text
|
.github/workflows/docker.yml
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Build docker image
|
2 |
+
|
3 |
+
on:
|
4 |
+
push:
|
5 |
+
branches:
|
6 |
+
- "main"
|
7 |
+
tags:
|
8 |
+
- "v*"
|
9 |
+
workflow_dispatch:
|
10 |
+
|
11 |
+
jobs:
|
12 |
+
push_to_registry:
|
13 |
+
name: Push Docker image to GitHub Packages
|
14 |
+
runs-on: ubuntu-latest
|
15 |
+
permissions:
|
16 |
+
contents: read
|
17 |
+
packages: write
|
18 |
+
steps:
|
19 |
+
- name: Check out the repo
|
20 |
+
uses: actions/checkout@v3
|
21 |
+
|
22 |
+
- name: Setup Docker
|
23 |
+
uses: docker/setup-buildx-action@v2
|
24 |
+
|
25 |
+
- name: Login to Docker Hub
|
26 |
+
uses: docker/login-action@v2
|
27 |
+
with:
|
28 |
+
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
29 |
+
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
30 |
+
|
31 |
+
- name: Login to Github Container Registry
|
32 |
+
uses: docker/login-action@v2
|
33 |
+
with:
|
34 |
+
registry: ghcr.io
|
35 |
+
username: ${{ github.repository_owner }}
|
36 |
+
password: ${{ secrets.GITHUB_TOKEN }}
|
37 |
+
|
38 |
+
- name: Generate Tags
|
39 |
+
uses: docker/metadata-action@v4
|
40 |
+
id: metadata
|
41 |
+
with:
|
42 |
+
images: |
|
43 |
+
${{ github.repository }}
|
44 |
+
ghcr.io/${{ github.repository }}
|
45 |
+
tags: |
|
46 |
+
type=ref,event=branch
|
47 |
+
type=ref,event=pr
|
48 |
+
type=semver,pattern={{version}}
|
49 |
+
|
50 |
+
- name: Build and Publish
|
51 |
+
uses: docker/build-push-action@v3
|
52 |
+
with:
|
53 |
+
context: .
|
54 |
+
platforms: linux/amd64,linux/arm64
|
55 |
+
push: true
|
56 |
+
tags: ${{ steps.metadata.outputs.tags }}
|
57 |
+
labels: ${{ steps.metadata.outputs.labels }}
|
58 |
+
cache-from: type=gha
|
59 |
+
cache-to: type=gha,mode=max
|
60 |
+
|
61 |
+
- name: Docker Hub Description
|
62 |
+
uses: peter-evans/dockerhub-description@v3
|
63 |
+
with:
|
64 |
+
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
65 |
+
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
66 |
+
readme-filepath: ./docs/docker.md
|
.github/workflows/publish.yml
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: publish
|
2 |
+
|
3 |
+
on:
|
4 |
+
push:
|
5 |
+
tags:
|
6 |
+
- v*
|
7 |
+
|
8 |
+
jobs:
|
9 |
+
release:
|
10 |
+
runs-on: ubuntu-latest
|
11 |
+
steps:
|
12 |
+
- uses: actions/checkout@v3
|
13 |
+
|
14 |
+
- name: Publish python package
|
15 |
+
uses: JRubics/poetry-publish@v1.16
|
16 |
+
with:
|
17 |
+
pypi_token: ${{ secrets.PYPI_TOKEN }}
|
.github/workflows/update.yml
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Update resource_list.json & memes.md
|
2 |
+
|
3 |
+
on:
|
4 |
+
push:
|
5 |
+
branches:
|
6 |
+
- "main"
|
7 |
+
paths:
|
8 |
+
- "meme_generator/memes/**"
|
9 |
+
workflow_dispatch:
|
10 |
+
|
11 |
+
jobs:
|
12 |
+
update-and-push:
|
13 |
+
runs-on: ubuntu-latest
|
14 |
+
steps:
|
15 |
+
- uses: actions/checkout@v3
|
16 |
+
|
17 |
+
- name: Setup python
|
18 |
+
uses: actions/setup-python@v3
|
19 |
+
with:
|
20 |
+
python-version: "3.10"
|
21 |
+
|
22 |
+
- name: Setup Poetry
|
23 |
+
uses: Gr1N/setup-poetry@v8
|
24 |
+
|
25 |
+
- name: Install dependencies
|
26 |
+
run: poetry install
|
27 |
+
|
28 |
+
- name: Install fonts
|
29 |
+
run: |
|
30 |
+
sudo apt install fonts-noto-cjk fonts-noto-color-emoji
|
31 |
+
sudo locale-gen zh_CN zh_CN.UTF-8
|
32 |
+
sudo update-locale LC_ALL=zh_CN.UTF-8 LANG=zh_CN.UTF-8
|
33 |
+
sudo mkdir /usr/share/fonts/myfonts
|
34 |
+
sudo cp resources/fonts/* /usr/share/fonts/myfonts/
|
35 |
+
fc-cache -fv
|
36 |
+
|
37 |
+
- name: Update resource_list.json
|
38 |
+
run: poetry run python resources/update_list.py
|
39 |
+
|
40 |
+
- name: Update memes.md
|
41 |
+
run: poetry run python docs/update_doc.py
|
42 |
+
|
43 |
+
- name: Commit & Push changes
|
44 |
+
uses: actions-js/push@master
|
45 |
+
with:
|
46 |
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
47 |
+
branch: "main"
|
.github/workflows/update_poetry_lock.yml
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: Update poetry.lock
|
2 |
+
|
3 |
+
on:
|
4 |
+
push:
|
5 |
+
branches:
|
6 |
+
- "main"
|
7 |
+
paths:
|
8 |
+
- "pyproject.toml"
|
9 |
+
workflow_dispatch:
|
10 |
+
|
11 |
+
jobs:
|
12 |
+
update-and-push:
|
13 |
+
runs-on: ubuntu-latest
|
14 |
+
steps:
|
15 |
+
- uses: actions/checkout@v3
|
16 |
+
|
17 |
+
- name: Setup python
|
18 |
+
uses: actions/setup-python@v3
|
19 |
+
with:
|
20 |
+
python-version: "3.10"
|
21 |
+
|
22 |
+
- name: Setup Poetry
|
23 |
+
uses: Gr1N/setup-poetry@v8
|
24 |
+
|
25 |
+
- name: Update poetry.lock
|
26 |
+
run: poetry update --lock
|
27 |
+
|
28 |
+
- name: Commit & Push changes
|
29 |
+
uses: actions-js/push@master
|
30 |
+
with:
|
31 |
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
32 |
+
branch: "main"
|
.gitignore
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*__pycache__/
|
2 |
+
dist/
|
3 |
+
.vscode/
|
4 |
+
.idea/
|
5 |
+
venv/
|
6 |
+
.venv/
|
7 |
+
|
8 |
+
result.png
|
9 |
+
result.jpg
|
10 |
+
result.gif
|
.pre-commit-config.yaml
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
default_install_hook_types: [pre-commit, prepare-commit-msg]
|
2 |
+
ci:
|
3 |
+
autofix_commit_msg: ":rotating_light: auto fix by pre-commit hooks"
|
4 |
+
autofix_prs: true
|
5 |
+
autoupdate_branch: master
|
6 |
+
autoupdate_schedule: monthly
|
7 |
+
autoupdate_commit_msg: ":arrow_up: auto update by pre-commit hooks"
|
8 |
+
repos:
|
9 |
+
- repo: https://github.com/hadialqattan/pycln
|
10 |
+
rev: v2.1.3
|
11 |
+
hooks:
|
12 |
+
- id: pycln
|
13 |
+
args: [--config, pyproject.toml]
|
14 |
+
|
15 |
+
- repo: https://github.com/pycqa/isort
|
16 |
+
rev: 5.12.0
|
17 |
+
hooks:
|
18 |
+
- id: isort
|
19 |
+
stages: [commit]
|
20 |
+
|
21 |
+
- repo: https://github.com/psf/black
|
22 |
+
rev: 23.1.0
|
23 |
+
hooks:
|
24 |
+
- id: black
|
25 |
+
stages: [commit]
|
26 |
+
|
Dockerfile
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.10 as tmp
|
2 |
+
|
3 |
+
WORKDIR /tmp
|
4 |
+
|
5 |
+
ENV PATH="${PATH}:/root/.local/bin"
|
6 |
+
|
7 |
+
COPY ./pyproject.toml ./poetry.lock* /tmp/
|
8 |
+
RUN pip install poetry \
|
9 |
+
&& poetry config virtualenvs.in-project true \
|
10 |
+
&& poetry install --only main --no-interaction --no-ansi
|
11 |
+
|
12 |
+
FROM python:3.10-slim as app
|
13 |
+
|
14 |
+
WORKDIR /app
|
15 |
+
|
16 |
+
EXPOSE 7860
|
17 |
+
|
18 |
+
VOLUME /data
|
19 |
+
|
20 |
+
COPY --from=tmp /tmp/.venv /app/.venv
|
21 |
+
|
22 |
+
COPY ./resources/fonts/* /usr/share/fonts/meme-fonts/
|
23 |
+
RUN apt-get update \
|
24 |
+
&& apt-get install -y --no-install-recommends locales fontconfig fonts-noto-cjk fonts-noto-color-emoji gettext \
|
25 |
+
&& localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8 \
|
26 |
+
&& fc-cache -fv \
|
27 |
+
&& apt-get purge -y --auto-remove \
|
28 |
+
&& rm -rf /var/lib/apt/lists/*
|
29 |
+
|
30 |
+
ENV TZ=Asia/Shanghai \
|
31 |
+
LC_ALL=zh_CN.UTF-8 \
|
32 |
+
PATH="/app/.venv/bin:${PATH}" \
|
33 |
+
VIRTUAL_ENV="/app/.venv" \
|
34 |
+
LOAD_BUILTIN_MEMES=true \
|
35 |
+
MEME_DIRS="[\"/data/memes\"]" \
|
36 |
+
MEME_DISABLED_LIST="[]" \
|
37 |
+
GIF_MAX_SIZE=10.0 \
|
38 |
+
GIF_MAX_FRAMES=100 \
|
39 |
+
BAIDU_TRANS_APPID="" \
|
40 |
+
BAIDU_TRANS_APIKEY="" \
|
41 |
+
LOG_LEVEL="INFO"
|
42 |
+
|
43 |
+
COPY ./meme_generator /app/meme_generator
|
44 |
+
|
45 |
+
COPY ./docker/config.toml.template /app/config.toml.template
|
46 |
+
COPY ./docker/start.sh /app/start.sh
|
47 |
+
RUN chmod +x /app/start.sh
|
48 |
+
|
49 |
+
CMD ["/app/start.sh"]
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2021 MeetWq
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
docker/config.toml.template
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[meme]
|
2 |
+
load_builtin_memes = $LOAD_BUILTIN_MEMES
|
3 |
+
meme_dirs = $MEME_DIRS
|
4 |
+
meme_disabled_list = $MEME_DISABLED_LIST
|
5 |
+
|
6 |
+
[gif]
|
7 |
+
gif_max_size = $GIF_MAX_SIZE
|
8 |
+
gif_max_frames = $GIF_MAX_FRAMES
|
9 |
+
|
10 |
+
[translate]
|
11 |
+
baidu_trans_appid = "$BAIDU_TRANS_APPID"
|
12 |
+
baidu_trans_apikey = "$BAIDU_TRANS_APIKEY"
|
13 |
+
|
14 |
+
[server]
|
15 |
+
host = "0.0.0.0"
|
16 |
+
port = 2233
|
17 |
+
|
18 |
+
[log]
|
19 |
+
log_level = "$LOG_LEVEL"
|
docker/start.sh
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#! /usr/bin/env bash
|
2 |
+
|
3 |
+
mkdir -p ~/.config/meme_generator
|
4 |
+
|
5 |
+
envsubst < /app/config.toml.template > ~/.config/meme_generator/config.toml
|
6 |
+
|
7 |
+
exec python -m meme_generator.app
|
docs/develop.md
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 新表情编写指北
|
2 |
+
|
3 |
+
## 表情注册
|
4 |
+
|
5 |
+
meme-generator 会以包的形式加载表情,通过 `add_meme` 函数来“注册”一个表情
|
6 |
+
|
7 |
+
以 `petpet` 表情为例,文件结构如下:
|
8 |
+
|
9 |
+
```
|
10 |
+
meme_generator/memes/petpet
|
11 |
+
├── __init__.py # 表情制作程序
|
12 |
+
└── images # 表情需要的图片文件
|
13 |
+
├── 0.png
|
14 |
+
├── 1.png
|
15 |
+
├── 2.png
|
16 |
+
├── 3.png
|
17 |
+
└── 4.png
|
18 |
+
```
|
19 |
+
|
20 |
+
在不考虑额外参数的情况下,`petpet` 表情的 `__init__.py` 编写如下:
|
21 |
+
|
22 |
+
```python
|
23 |
+
from typing import List
|
24 |
+
from pathlib import Path
|
25 |
+
from pil_utils import BuildImage
|
26 |
+
from PIL.Image import Image as IMG
|
27 |
+
|
28 |
+
from meme_generator.utils import save_gif
|
29 |
+
from meme_generator import add_meme
|
30 |
+
|
31 |
+
|
32 |
+
img_dir = Path(__file__).parent / "images"
|
33 |
+
|
34 |
+
|
35 |
+
def petpet(images: List[BuildImage], texts, args):
|
36 |
+
"""表情制作函数
|
37 |
+
|
38 |
+
函数会接收 3 个参数:
|
39 |
+
- `images`: 传入的图片列表,类型为 `pil_utils.BuildImage`
|
40 |
+
- `texts`: 传入的文字列表,类型为 `str`
|
41 |
+
- `args`: 其他参数,类型为 `meme_generator.meme.MemeArgsModel`
|
42 |
+
"""
|
43 |
+
img = images[0].convert("RGBA").square()
|
44 |
+
frames: List[IMG] = []
|
45 |
+
locs = [
|
46 |
+
(14, 20, 98, 98),
|
47 |
+
(12, 33, 101, 85),
|
48 |
+
(8, 40, 110, 76),
|
49 |
+
(10, 33, 102, 84),
|
50 |
+
(12, 20, 98, 98),
|
51 |
+
]
|
52 |
+
for i in range(5):
|
53 |
+
hand = BuildImage.open(img_dir / f"{i}.png")
|
54 |
+
frame = BuildImage.new("RGBA", hand.size, (255, 255, 255, 0))
|
55 |
+
x, y, w, h = locs[i]
|
56 |
+
frame.paste(img.resize((w, h)), (x, y), alpha=True)
|
57 |
+
frame.paste(hand, alpha=True)
|
58 |
+
frames.append(frame.image)
|
59 |
+
return save_gif(frames, 0.06)
|
60 |
+
|
61 |
+
|
62 |
+
add_meme(
|
63 |
+
"petpet", # 表情唯一名
|
64 |
+
petpet, # 表情制作函数
|
65 |
+
min_images=1, # 至少需要 1 张图片
|
66 |
+
max_images=1, # 另有 `min_texts` 和 `max_texts` 选项来控制传入文字的数量
|
67 |
+
keywords=["摸", "摸摸", "摸头", "rua"], # 关键词,填写言简意赅的词语,用于展示表情含义、方便聊天Bot调用等
|
68 |
+
)
|
69 |
+
```
|
70 |
+
|
71 |
+
通常情况下,建议每个表情一个文件夹,表情所需的图片文件等都放置于该文件夹中,方便增删表情
|
72 |
+
|
73 |
+
也可以一个文件中注册多个表情,如:[gif_subtitle](../meme_generator/memes/gif_subtitle/__init__.py)
|
74 |
+
|
75 |
+
|
76 |
+
## 参数定义
|
77 |
+
|
78 |
+
部分表情需要额外的参数。表情参数的类型定义如下:
|
79 |
+
|
80 |
+
```python
|
81 |
+
@dataclass
|
82 |
+
class MemeArgsType:
|
83 |
+
parser: MemeArgsParser # 参数解析器,将命令行形式的文本解析为字典形式,方便通过命令行使用
|
84 |
+
model: Type[MemeArgsModel] # 参数模型,用于验证字典形式的参数,并传入表情制作函数
|
85 |
+
instances: List[MemeArgsModel] = field(default_factory=list) # 可选,参数模型示例,推荐填写,方便生成不同参数下的预览图
|
86 |
+
```
|
87 |
+
|
88 |
+
以 `petpet` 表情为例,需要定义一个控制图片是否变为圆形的参数 `circle`
|
89 |
+
|
90 |
+
可以定义如下的 `pydantic` 模型:
|
91 |
+
|
92 |
+
```python
|
93 |
+
from pydantic import Field
|
94 |
+
from meme_generator import MemeArgsModel
|
95 |
+
|
96 |
+
class Model(MemeArgsModel):
|
97 |
+
circle: bool = Field(False, description="是否将图片变为圆形")
|
98 |
+
```
|
99 |
+
|
100 |
+
定义参数时推荐使用 `Field` 定义默认值,可以定义 `description` 描述参数含义,方便生成文档
|
101 |
+
|
102 |
+
同时定义如下的参数解析器:
|
103 |
+
|
104 |
+
```python
|
105 |
+
from meme_generator import MemeArgsParser
|
106 |
+
|
107 |
+
parser = MemeArgsParser(prefix_chars="-/")
|
108 |
+
parser.add_argument("--circle", "/圆", action="store_true", help="是否将图片变为圆形")
|
109 |
+
```
|
110 |
+
|
111 |
+
以上参数解析器可以将形如 `["--circle"]` 的参数列表解析为 `{"circle": true}` 的形式,继而通过 `pydantic` 模型验证
|
112 |
+
|
113 |
+
推荐在定义选项时添加自然语言风格的别名,如 `/圆`,这样可以方便聊天机器人等场合调用,比如可以解析 `摸头 /圆` 这样的文本
|
114 |
+
|
115 |
+
定义好上述的 `parser` 和 `Model` 后,需要在 `add_meme` 时传入:
|
116 |
+
|
117 |
+
```python
|
118 |
+
add_meme(
|
119 |
+
"petpet",
|
120 |
+
petpet,
|
121 |
+
min_images=1,
|
122 |
+
max_images=1,
|
123 |
+
args_type=MemeArgsType(
|
124 |
+
parser,
|
125 |
+
Model,
|
126 |
+
[
|
127 |
+
Model(circle=False),
|
128 |
+
Model(circle=True),
|
129 |
+
],
|
130 |
+
),
|
131 |
+
keywords=["摸", "摸摸", "摸头", "rua"],
|
132 |
+
)
|
133 |
+
```
|
134 |
+
|
135 |
+
这里传入了 `circle=False` 和 `circle=True` 两个模型实例,可以在生成文档时生成不同参数时的预览图,效果如 [memes.md](memes.md#petpet) 所示
|
docs/docker.md
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
https://github.com/MeetWq/meme-generator
|
2 |
+
|
3 |
+
## Docker部署
|
4 |
+
|
5 |
+
### 运行
|
6 |
+
|
7 |
+
```shell
|
8 |
+
docker run -d \
|
9 |
+
--name=meme-generator \
|
10 |
+
-p 2233:2233 \
|
11 |
+
--restart always \
|
12 |
+
meetwq/meme-generator:latest
|
13 |
+
```
|
14 |
+
|
15 |
+
运行后可通过 api 方式调用
|
16 |
+
|
17 |
+
|
18 |
+
### 环境变量
|
19 |
+
|
20 |
+
| 变量名 | 默认值 | 说明 |
|
21 |
+
| --- | --- | --- |
|
22 |
+
| `MEME_DIRS` | `'["/data/memes"]'` | 额外表情路径 |
|
23 |
+
| `MEME_DISABLED_LIST` | `'[]'` | 禁用表情列表 |
|
24 |
+
| `GIF_MAX_SIZE` | `10.0` | 限制生成的 gif 文件大小 |
|
25 |
+
| `GIF_MAX_FRAMES` | `100` | 限制生成的 gif 文件帧数 |
|
26 |
+
| `BAIDU_TRANS_APPID` | `''` | 百度翻译 appid |
|
27 |
+
| `BAIDU_TRANS_APIKEY` | `''` | 百度翻译 apikey |
|
28 |
+
| `LOG_LEVEL` | `'INFO'` | 日志等级 |
|
29 |
+
|
30 |
+
|
31 |
+
### 加载额外表情
|
32 |
+
|
33 |
+
可通过 `MEME_DIRS` 环境变量指定额外表情路径,默认为 `["/data/memes"]`
|
34 |
+
|
35 |
+
可将 docker 路径 `/data` 映射到本地路径 `<YOUR_DATA_DIR>`
|
36 |
+
|
37 |
+
将额外表情放置于 `<YOUR_DATA_DIR>/memes` 即可
|
38 |
+
|
39 |
+
|
40 |
+
完整的运行示例:
|
41 |
+
|
42 |
+
```shell
|
43 |
+
docker run -d \
|
44 |
+
--name=meme-generator \
|
45 |
+
-p 2233:2233 \
|
46 |
+
--restart always \
|
47 |
+
-v <YOUR_DATA_DIR>:/data \
|
48 |
+
-e MEME_DIRS='["/data/memes"]' \
|
49 |
+
-e MEME_DISABLED_LIST='[]' \
|
50 |
+
-e GIF_MAX_SIZE=10.0 \
|
51 |
+
-e GIF_MAX_FRAMES=100 \
|
52 |
+
-e BAIDU_TRANS_APPID=<YOUR_BAIDU_TRANS_APPID> \
|
53 |
+
-e BAIDU_TRANS_APIKEY=<YOUR_BAIDU_TRANS_APIKEY> \
|
54 |
+
-e LOG_LEVEL='INFO' \
|
55 |
+
meetwq/meme-generator:main
|
56 |
+
```
|
docs/examples/avatar.jpg
ADDED
docs/examples/test_api.py
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import asyncio
|
2 |
+
import json
|
3 |
+
|
4 |
+
import httpx
|
5 |
+
|
6 |
+
|
7 |
+
async def main():
|
8 |
+
files = [("images", open("avatar.jpg", "rb"))]
|
9 |
+
texts = []
|
10 |
+
args = {"circle": True}
|
11 |
+
data = {"texts": texts, "args": json.dumps(args)}
|
12 |
+
|
13 |
+
url = "http://127.0.0.1:2233/memes/petpet/"
|
14 |
+
async with httpx.AsyncClient() as client:
|
15 |
+
resp = await client.post(url, files=files, data=data)
|
16 |
+
|
17 |
+
with open("result.gif", "wb") as f:
|
18 |
+
f.write(resp.content)
|
19 |
+
|
20 |
+
|
21 |
+
if __name__ == "__main__":
|
22 |
+
loop = asyncio.new_event_loop()
|
23 |
+
loop.run_until_complete(main())
|
docs/examples/test_meme.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import asyncio
|
2 |
+
|
3 |
+
from meme_generator import get_meme
|
4 |
+
|
5 |
+
|
6 |
+
async def main():
|
7 |
+
meme = get_meme("petpet")
|
8 |
+
result = await meme(images=["avatar.jpg"], texts=[], args={"circle": True})
|
9 |
+
|
10 |
+
with open("result.gif", "wb") as f:
|
11 |
+
f.write(result.getvalue())
|
12 |
+
|
13 |
+
|
14 |
+
if __name__ == "__main__":
|
15 |
+
loop = asyncio.new_event_loop()
|
16 |
+
loop.run_until_complete(main())
|
docs/images/5000choyen.jpg
ADDED
docs/images/acg_entrance.jpg
ADDED
docs/images/add_chaos.jpg
ADDED
docs/images/addiction.jpg
ADDED
docs/images/alike.jpg
ADDED
docs/images/always.jpg
ADDED
docs/images/always_instance0.jpg
ADDED
docs/images/always_instance1.jpg
ADDED
docs/images/always_instance2.gif
ADDED
docs/images/always_like.jpg
ADDED
docs/images/anti_kidnap.jpg
ADDED
docs/images/anya_suki.jpg
ADDED
docs/images/applaud.gif
ADDED
docs/images/ascension.jpg
ADDED
docs/images/ask.png
ADDED
docs/images/back_to_work.jpg
ADDED
docs/images/bad_news.png
ADDED
docs/images/beat_head.gif
ADDED
docs/images/bite.gif
ADDED
docs/images/blood_pressure.jpg
ADDED
docs/images/bocchi_draft.gif
ADDED
Git LFS Details
|
docs/images/bronya_holdsign.jpg
ADDED
docs/images/bubble_tea.jpg
ADDED
docs/images/bubble_tea_instance0.jpg
ADDED
docs/images/bubble_tea_instance1.jpg
ADDED
docs/images/bubble_tea_instance2.jpg
ADDED
docs/images/call_110.jpg
ADDED
docs/images/caoshen_bite.gif
ADDED
Git LFS Details
|
docs/images/capoo_draw.gif
ADDED
docs/images/capoo_rip.gif
ADDED
docs/images/capoo_rub.gif
ADDED
docs/images/capoo_say.gif
ADDED
docs/images/capoo_strike.gif
ADDED
docs/images/captain.jpg
ADDED