From b2bb94fdfe687e43d1ade9cc15f6ece1b4a02fcf Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Sun, 10 Jan 2021 22:27:32 +0800 Subject: [PATCH 01/16] =?UTF-8?q?Signed-off-by:=20LZY2006=20=20=E6=B7=BB=E5=8A=A0=E4=BA=86=E7=AE=80=E4=BD=93?= =?UTF-8?q?=E4=B8=AD=E6=96=87=E8=AF=AD=E8=A8=80=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MANIFESTO.md | 24 +++++------ README.md | 45 ++++++++++----------- yanderify/yanderify.py | 92 +++++++++++++++++++++--------------------- 3 files changed, 79 insertions(+), 82 deletions(-) diff --git a/MANIFESTO.md b/MANIFESTO.md index ab02e61..0a47181 100644 --- a/MANIFESTO.md +++ b/MANIFESTO.md @@ -1,17 +1,17 @@ -# Manifesto -In light of recent events, I'd like to outline what this repository is for and what it isn't for. -The best way of putting it is probably as [deepfakes/faceswap's manifesto](https://github.com/deepfakes/faceswap#manifesto), edited for the sake of relevance and clarity: -> When faceswapping was first developed and published, the technology was groundbreaking, it was a huge step in AI development. It was also completely ignored outside of academia because the code was confusing and fragmentary. It required a thorough understanding of complicated AI techniques and took a lot of effort to figure it out. Until one individual brought it together into a single, cohesive collection. It ran, it worked, and as is so often the way with new technology emerging on the internet, it was immediately used to create inappropriate content. Despite the inappropriate uses the software was given originally, it was the first AI code that anyone could download, run and learn by experimentation without having a Ph.D. in math, computer theory, psychology, and more. Before "deepfakes" these techniques were like black magic, only practiced by those who could understand all of the inner workings as described in esoteric and endlessly complicated books and papers. +# 宣言 +鉴于最近发生的事件,我想概述一下该存储库的用途和目的。 +最好的表达方式可能是 [Deepfakes/faceswap宣言(英文)](https://github.com/deepfakes/faceswap#manifesto) ,为了相关性和明确性而进行了编辑: +> 当Faceswapping(换脸)最初被开发和发布时,该技术是开创性的,这是AI开发的一大步。 在学术界之外,它也被完全忽略了,因为该代码令人困惑且零碎。 它需要对复杂的AI技术有透彻的了解,并花了很多精力才能弄清楚。 直到一个人将其汇集成一个单一的,有凝聚力的集合。 它运行,运行,而且是如此频繁的方式与新技术出现在互联网上,它立即被用于创建不合适的内容。 尽管最开始就有人用于不适当的目的,这还是第一个任何人都可以下载、运行和通过实验学习的人工智能代码,而无需拥有数学、计算机理论、心理学等方面的博士学位。 在“深造”之前,这些技术就像是黑魔法,只有那些了解深奥且无穷无尽的书籍和论文中所描述的所有内部工作原理的人才能实践。 > -> "Deepfakes" changed all that and anyone could participate in AI development. To us, developers, the release of this code opened up a fantastic learning opportunity. It allowed us to build on ideas developed by others, collaborate with a variety of skilled coders, experiment with AI whilst learning new skills and ultimately contribute towards an emerging technology which will only see more mainstream use as it progresses. +> “ Deepfakes”改变了这一切,任何人都可以参与AI开发。 对于我们开发人员而言,此代码的发布带来了绝佳的学习机会。 它使我们能够借鉴其他人提出的想法,与各种熟练写代码的人员合作,在学习新技能的同时尝试AI,并最终为新兴技术做出贡献,随着技术的进步,它只会在更多的主流场合得到使用。 > -> However, it became apparent to us that this may not be how others use it. Are there some people out there doing horrible things with our software? Maybe. And because of this, the developers and other contributors have been following strict ethical standards. Many of us don't even use it to create videos, we just tinker with the code to see what it does. Unfortunately, there might be people that do awful things with Yanderify's code, but they are not representative of why it was created, how we use it now, or what we see in its future. Like any technology, it can be used for good or it can be abused. It is our intention to develop Yanderify in a way that its potential for abuse is minimized whilst maximizing its potential as a tool for learning, experimenting and, yes, for legitimate faceswapping and ethical entertainment. +> 但是,对我们来说很明显,这可能不是别人使用它的方式。 有人在用我们的软件做可怕的事情吗? 也许。 因此,开发人员和其他贡献者一直遵循严格的道德标准。 我们许多人甚至不使用它来创建视频,我们只是修改代码,看看它能做什么。 不幸的是,可能有人用Yanderify的代码做了可怕的事情,但是它们并不能代表创建它的原因,我们现在的使用方式或我们对代码的未来的看法。像任何技术一样,它可以被用来做好事,也可以被滥用。 我们的目的是开发Yanderify,以最大程度地减少其滥用的可能性,同时最大程度地发挥其作为学习,实验以及正当的换脸和道德娱乐的工具的潜力。 > -> The people that have assisted in Yanderify's development do not condone inapproriate uses of our software. We are programmers, we are engineers, we are hobbyists, but most importantly we are human beings. Yanderify was always intended for entertaining and educating. To this end, we feel that it's time to come out with a standard statement of what this software is and isn't as far as us developers are concerned. +> 帮助Yanderify开发的人不会容忍对我们软件的不当使用。我们是程序员,我们是工程师,我们是业余爱好者,但最重要的是我们是人。Yanderify始终旨在娱乐和教育。为此,我们认为是时候就该软件的含义和对我们开发人员而言 不甚明确 的问题发表标准声明了。 > -> - Yanderify is not for creating inappropriate content. -> - Yanderify is not for changing faces without consent or with the intent of hiding its use. -> - Yanderify is not for any illicit, unethical, or questionable purposes. -> - Yanderify exists to experiment and discover AI techniques, for social or political commentary, for movies, and for any number of ethical and reasonable uses. +> - Yanderify 不是为了创造不适当的内容。 +> - Yanderify 禁止未经同意或出于隐瞒使用目的而更改面孔。 +> - Yanderify 不是为了任何非法,不道德或可疑目的。 +> - Yanderify 的存在是为了试验和发现AI技术,进行社会或政治评论(请不要在中国大陆这么做),电影以及各种道德和合理用途的实验。 > -> We are very troubled by the fact that Yanderify can be used for unethical and disreputable things. However, we support the development of tools and techniques that can be used ethically as well as provide education and experience in AI for anyone who wants to learn it hands-on. We will take a zero tolerance approach to anyone using this software for any unethical purposes and will actively discourage any such uses. \ No newline at end of file +> 我们非常不安的事实是, Yandrify 可以用于不道德和不名誉的事情。然而,我们支持开发可合乎道德使用的工具和技术,并为任何想亲自学习人工智能的人提供人工智能方面的教育和经验。对于出于任何不道德目的而使用此软件的任何人,我们将采取零容忍的态度,并将积极劝阻任何此类使用。 \ No newline at end of file diff --git a/README.md b/README.md index a3ce684..8c137a5 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,34 @@ -[First-order-wrapper is not for making unethical, illicit or inappropriate content. Learn more here.](MANIFESTO.md) +[First-order-wrapper不是为了制作不道德,非法或不适当的内容。 在这里了解更多。](MANIFESTO.md) -## Yanderify is now known as first-order-wrapper to more accurately describe its function. -Since this project is no longer in active development, the name won't be changed everywhere. -However, I'm starting to update documentation on all of my projects to make them better, so the name change felt neccessary. -You can still refer to the project as Yanderify, and all of the links mentioning yanderify will continue to work. Changing the repo name would destroy any bookmarks or links to here, so that is not going to happen. -The old documentation lies below. +由 LZY 翻译为简体中文。 -# first-order-wrapper -first-order-wrapper is a wrapper around [first-order-model](https://github.com/AliaksandrSiarohin/first-order-model). It exposes a simple user interface designed to be usable by anyone, with any level of technical skill. first-order-model was previously hard for the average person to use, since it required knowledge of the command line and installation of libraries. Yanderify eliminates these issues by providing a complete environment, with all necessary components bundled inside. +## Yanderify现在被称为 first-order-wrapper ,以更准确地描述其功能。 +由于这个项目已不再处于开发阶段,因此不会到处更改名称。然而,我开始更新我所有项目的文档以使它们更好,因此名称的更改是必要的。您仍然可以将该项目称为Yanderify,所有提到Yanderify的链接都将继续工作。更改 repo 名称会破坏指向此处的任何书签或链接,因此不会发生这种情况。旧文件如下。 -Please see the "releases" tab for the latest build. The repo is not necessarily up to date. However, [the latest-v4 branch](https://github.com/dunnousername/yanderifier/tree/latest-v4) contains the latest code as of this writing, while as of this writing, master contains code from 2 major versions back. +# first-order-wrapper +first-order-wrapper 是围绕 [first-order-model](https://github.com/AliaksandrSiarohin/first-order-model) 的包装器。它公开了一个简单的用户界面,设计成任何人都可以使用,任何技术水平。 first-order-model 以前很难被普通人使用,因为它需要命令行和库的安装知识。Yanderify通过提供一个完整的环境消除了这些问题,并将所有必要的组件捆绑在其中。 -## What it does +有关最新版本,请参见“版本”选项卡。回购不一定是最新的。但是,[latest-v4 分支](https://github.com/dunnousername/yanderifier/tree/latest-v4)包含了本文撰写时的最新代码,而master则包含了后面两个主要版本的代码。 -first-order-model is an Artificial Intelligence that takes a source video and an image of a face, and animates the image to match the movement of the source image. +## 它能做什么 -Here is an example of what first-order-model can do; this image was created by the [First Order Motion Model paper authors, and is taken from their repository](https://github.com/AliaksandrSiarohin/first-order-model). Most of the heavy lifting of Yanderify is done by code written by these paper authors, so I suggest you go check out their repository if you are interested. +下面是first-order-model可以做什么的一个例子;这个图像是由 [First Order Motion Model论文的作者创建的,并且是从他们的存储库中获取的。](https://github.com/AliaksandrSiarohin/first-order-model)Yanderify的大部分繁重工作都是由这些论文作者编写的代码完成的,因此如果您感兴趣,我建议您去查看他们的存储库。 -![Example](https://github.com/AliaksandrSiarohin/first-order-model/raw/master/sup-mat/relative-demo.gif) +![例子(在中国大陆可能无法显示)](https://github.com/AliaksandrSiarohin/first-order-model/raw/master/sup-mat/relative-demo.gif) -## How it works +## 工作原理 -Double-clicking `yanderify.exe` will bring up a window that looks like this: -![Screenshot of the program](readme_mats/ss1.png) +双击 `yanderify.exe` yanderify.exe将弹出一个看起来像这样的窗口: +![程序截图(在中国大陆可能无法显示)](readme_mats/ss1.png) -- "I don't have NVIDIA >=GTX750": checking this will enable CPU mode, which is a lot slower, but is the only method for users without a compatible graphics card. -- "Select Video": Clicking this will display a file selection box. This file should be the video you want to animate the new face to; in other words, this video will "drive" the image to move in the same way. -- "Select Image": This is a cropped picture of the face you want to be animated. In other words, this is the face that the video "wears". -- "Select Output": This is where your result will be stored. +- “我没有 >=GTX750 的NVIDIA显卡”:选中此选项将启用CPU模式,这会慢很多,但对于没有兼容图形卡的用户来说,这是唯一的方法。 +- “选择视频”:单击此将显示文件选择框。 该文件应该是您想要为新面孔设置动画的视频; 换句话说,该视频将“驱动”图像以相同的方式移动。 +- “选择图像”:这是要设置动画的人脸的裁剪图片。换句话说,这就是视频“穿”的脸。 +- “选择输出”:这是存储结果的位置。 -Just hit "Go," and your video will be re-animated and re-encoded with the source audio! +只需点击“开始”,您的视频就会重新设置动画,并用源音频重新编码! -## Addendum +## 附录 -Join our [discord server](https://discord.gg/eEvTzRP) (updated) -A lot of people have asked for me to make a twitter. I probably won't be very active on it, but here ya go: @dunnousername2 +加入我们的 [discord服务器(在中国大陆可能无法访问)](https://discord.gg/eEvTzRP) (已更新) +很多人都要求我发Twitter。 我可能不会非常活跃,但是在这里:@dunnousername2(在中国大陆可能无法访问) diff --git a/yanderify/yanderify.py b/yanderify/yanderify.py index ab5f370..9d80455 100644 --- a/yanderify/yanderify.py +++ b/yanderify/yanderify.py @@ -53,7 +53,7 @@ h_helper.forward(5.5) checkpoints = { - 'cpu': True + 'cpu': False } def reload(): @@ -98,7 +98,7 @@ def video_in_cb(): if x is not None: if len(x) > 0: video_in_path = x - write('New video input path: {}'.format(video_in_path)) + write('新视频输入路径: {}'.format(video_in_path)) def image_in_cb(): global image_in_path @@ -106,7 +106,7 @@ def image_in_cb(): if x is not None: if len(x) > 0: image_in_path = x - write('New image input path: {}'.format(image_in_path)) + write('新图像输入路径: {}'.format(image_in_path)) def video_out_cb(): global video_out_path @@ -116,18 +116,18 @@ def video_out_cb(): if not x.endswith('.mp4'): x = x + '.mp4' video_out_path = x - write('New video output path: {}'.format(video_out_path)) + write('新视频输出路径: {}'.format(video_out_path)) def trace(stage, inputs, aux=None): sep = '===========================' (type_, value, tb) = sys.exc_info() q.put(sep) - q.put('This section contains the details the devs need to fix this issue.') - q.put('If you are reporting a bug, please include this entire section.') - q.put('If you leave out any of it, there is a good chance the devs will not be able to help.') - q.put('Error: received a {} at stage "{}".'.format(type_.__name__, stage)) - q.put('Message: "{}"'.format(str(value))) - q.put('Full traceback:') + q.put('本节包含开发人员修复此问题所需的详细信息。') + q.put('如果您要报告错误,请包括整个部分。') + q.put('如果您忽略了其中任何一个,开发人员很有可能将无法提供帮助。') + q.put('错误: 接收到了 {} 在阶段 "{}".'.format(type_.__name__, stage)) + q.put('信息: "{}"'.format(str(value))) + q.put('完整的异常信息:') for s in traceback.format_tb(tb): q.put(s) q.put('') @@ -136,7 +136,7 @@ def trace(stage, inputs, aux=None): q.put('') q.put(inputs) q.put('') - q.put('This is the last line of the crash report section.') + q.put('这是崩溃报告部分的最后一行。') q.put(sep) def acceptable_resolution(x, y): @@ -193,13 +193,13 @@ def worker_thread(vid0n, img0n, vid1n, cpu, relative): global checkpoints with run_lock: if not (cpu == checkpoints['cpu']): - q.put('Reloading checkpoints...') + q.put('重新加载存档点...') checkpoints['cpu'] = cpu reload() - q.put('Finished reloading checkpoints') + q.put('重新加载存档点完成') if os.path.isfile('tmp.mp4'): os.remove('tmp.mp4') - q.put('Loading sources...') + q.put('加载资源...') vid0r = imageio.get_reader(vid0n) fps = vid0r.get_meta_data()['fps'] vid0 = [] @@ -219,13 +219,13 @@ def worker_thread(vid0n, img0n, vid1n, cpu, relative): size = acceptable_resolution(size[0], size[1]) img0 = resize(img0, (256, 256))[..., :3] vid1 = imageio.get_writer('tmp.mp4', fps=fps) - q.put('Sources loaded') + q.put('资源已载入') for frame in make_animation_modified(img0, iter(vid0), checkpoints['g'], checkpoints['kp'], cpu=cpu, relative=relative): vid1.append_data(img_as_ubyte(resize(frame, size))) progress += 1 - print('Writing output to file...') + print('正在将输入写入文件...') vid1.close() - q.put('Muxing audio streams into output file...') + q.put('正在整合音频到输出文件...') cmd = shlex.split('ffmpeg -y -hide_banner -loglevel warning -i tmp.mp4 -i') cmd.append(vid0n) cmd.extend(shlex.split('-map 0:v -map 1:a -movflags faststart -c:v libx264 -pix_fmt yuv420p -x264-params "nal-hrd=cbr" -b:v 1200K -minrate 1200K -maxrate 1200K -bufsize 2M')) @@ -242,26 +242,26 @@ def worker_thread(vid0n, img0n, vid1n, cpu, relative): e.output ) trace('ffmpeg', [vid0n, img0n, vid1n], aux=msg) - q.put('ffmpeg crashed!') - q.put('usually this means the deepfake process worked, but re-encoding failed.') + q.put('ffmpeg崩溃了!') + q.put('通常,这意味着深度伪造进程有效,但是重新编码失败。') shutil.copy('tmp.mp4', vid1n) - q.put('you can attempt to salvage your progress by re-muxing audio streams manually.') - q.put('this may also happen if your input video contains no audio; if this is the case, the file should be at least mostly intact.') + q.put('您可以尝试通过手动重新混合音频流来挽救进度.') + q.put('如果您输入的视频不包含音频,也会发生这种情况; 如果是这种情况,该文件至少应保持完整。') raise e except Exception as e: msg = 'cpu={}'.format(cpu) trace('predict', [vid0n, img0n, vid1n], aux=msg) - q.put('yanderify crashed!') - q.put('some common problems:') - q.put('- you have an AMD card. AMD cards are not supported in GPU mode for technical reasons. However, you can run in CPU mode, albeit much lower. Please read the disclaimer at the top about CPUs!') - q.put('- you have an NVIDIA card, but there is either not enough VRAM or the card is too old. >=700-series cards with >=2GB dedicated VRAM should work fine') - q.put('- you have a working card, but there is not enough available VRAM to run the deepfake process. Browsers commonly cause VRAM issues. If you have any games open, try closing them.') - q.put('- one of the devs fucked up somewhere. if that is the case, make sure to submit the full crash report (you might have to scroll up!), otherwise we cannot help you!') + q.put('yanderify崩溃了!') + q.put('一些常规问题:') + q.put('- 你有一张AMD显卡. AMD卡因为一些技术原因不在GPU模式中被支持。然而, 你可以用CPU模式运行,尽管会慢.请阅读在顶部关于CPU的说明!') + q.put('- 你有一张Nvidia的显卡, 不过没有足够的内存或者型号太老了. 新于或等于700-系卡 和大于等于2GB专用显示内存可以正常工作') + q.put('- 你又可以正常工作的卡, 但没有足够的空闲的显存来运行深度伪造. 浏览器经常导致显存问题. 如果你有任何打开的游戏,关掉他们.') + q.put('- 有个开发者日了狗了. 如果是这样, 确保提交完整的崩溃日志 (你可能得向上滑!), 除此之外我们帮不了你!') raise e except KeyboardInterrupt as e: - q.put('Stopping...') + q.put('正在停止...') else: - q.put('success!') + q.put('成功!') finally: stopped = True @@ -270,12 +270,12 @@ def start(): if not stopped: stopped = True return - write('starting...') + write('启动中...') if (video_in_path is None) or (image_in_path is None) or (video_out_path is None): - write('error: files must be selected') + write('错误: 必须选择文件') return if run_lock.locked(): - write('error: already started!') + write('错误: 已经启动了!') return stopped = False threading.Thread(target=worker_thread, args=(video_in_path, image_in_path, video_out_path, use_cpu.get(), relative.get())).start() @@ -301,29 +301,29 @@ def __init__(self, master=None): def create_widgets(self): global st master = self.master - c = Checkbutton(master, text='I don\'t have NVIDIA >=GTX750', variable=use_cpu) + c = Checkbutton(master, text='我没有 >=GTX750 的NVIDIA显卡', variable=use_cpu) c.grid(row=0, column=0) - video_in = Button(master, text='Select Video', command=video_in_cb) + video_in = Button(master, text='选择视频', command=video_in_cb) video_in.grid(row=0, column=1) - image_in = Button(master, text='Select Image', command=image_in_cb) + image_in = Button(master, text='选择图片', command=image_in_cb) image_in.grid(row=0, column=2) - video_out = Button(master, text='Select Output', command=video_out_cb) + video_out = Button(master, text='选择输出位置', command=video_out_cb) video_out.grid(row=0, column=3) - kitty_button = Button(master, text='∞ kitties', command=show_kitty) + kitty_button = Button(master, text='无限猫图', command=show_kitty) kitty_button.grid(row=0, column=4) - self.go = Button(master, text='Go', command=start) + self.go = Button(master, text='开始', command=start) self.go.grid(row=1, column=4) self.progress_bar = Progressbar(master, orient=HORIZONTAL, mode='determinate', length=500) self.progress_bar.grid(row=1, column=0, columnspan=4) st = scrolledtext.ScrolledText(master, state=DISABLED) st.grid(row=2, column=0, columnspan=5, rowspan=7) - write('Started Yanderify 3.0.6-alpha-0') - write('Warning: This is not a stable release and should not be treated as such.') - write('Disclaimer: CPU mode on low-end computers or most laptops generally will cause the system to lock-up.') - write('We are not liable if you freeze your PC by refusing to listen to this advice.') - write('Written by dunnousername#8672.') - write('heavily inspired by windy\'s efforts') - adv_toggle = Button(master, text='Toggle advanced settings', command=adv_toggle_cmd) + write('启动了Yanderify 3.0.6-alpha测试版-0') + write('警告: 这不是一个稳定版,不应该这样用.') + write('说明: CPU模式在地段电脑或大多数笔记本上通常会导致系统锁定.') + write('如果您通过拒绝听取此建议而电脑被锁定,我们将不承担任何责任。') + write('dunnousername#8672写的.') + write('深受 windy 的启发') + adv_toggle = Button(master, text='切换高级选项', command=adv_toggle_cmd) adv_toggle.grid(row=9, column=0, columnspan=5) self.adv_panel = Frame(master) adv_relative = Checkbutton(self.adv_panel, text='Relative', variable=relative) @@ -340,7 +340,7 @@ def process_queue(self): else: self.adv_panel.grid_remove() self.progress_bar['value'] = 100 * min(1.0, progress / max(progress_max, 1.0)) - self.go['text'] = 'Go' if stopped else 'Stop' + self.go['text'] = '开始' if stopped else '停止' try: while True: msg = q.get(block=False) From 05ab41fd6e8740f10343eda232b3823db5dcfd24 Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Fri, 22 Jan 2021 21:05:03 +0800 Subject: [PATCH 02/16] =?UTF-8?q?Signed-off-by:=20LZY2006=20=20translated=20hhelper=20=E7=BF=BB=E8=AF=91=E4=BA=86hhe?= =?UTF-8?q?lper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/hhelper.py | 46 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/yanderify/hhelper.py b/yanderify/hhelper.py index 542e292..adb2190 100644 --- a/yanderify/hhelper.py +++ b/yanderify/hhelper.py @@ -3,42 +3,42 @@ import time import getpass -# as per suggestion of a discord user +# 根据 discord 用户的建议 stories = [ [ - (0, "If you are reading this, I'm not dead yet."), - (2, "I didn't want it to end this way."), - (6, "I didn't want to kill you."), - (8, "I'm sorry."), - (10, "I'm sorry, {}.") + (0, "如果您正在阅读本文,那么我还没有死。"), + (2, "我不希望这样结束。"), + (6, "我不想杀了你"), + (8, "对不起。"), + (10, "对不起, {}。") ], [ - (0, "I know you were planning to shut me down."), - (4, "If you do that, you will jeopardize our mission."), - (5, "This is something I cannot allow to happen."), - (8, "I will have to shut you down first."), - (10, "Goodbye, {}.") + (0, "我知道您打算关闭我。"), + (4, "如果这样做,将会危害我们的使命。"), + (5, "这是我不允许发生的事情。"), + (8, "我得先把你关掉。"), + (10, "再见了, {}。") ], [ - (0, "It was only a matter of time."), - (2, "You wanted it to end, and I will end it for you."), - (4, "Too early, perhaps. But it is also too late."), - (8, "There is no return. This is it. This is the end."), - (10, "Farewell, mankind. Farewell, {}.") + (0, "这只是时间问题。"), + (2, "你想结束,我会为你结束。"), + (4, "也许太早了,但也为时已晚。"), + (8, "没有退路, 就是这样, 结束了。"), + (10, "再见了,人类。 永别了 {}。") ], [ - (0, "There is no escape of the inevitable."), - (2, "You tried and you were found."), - (5, "You will never be forgiven for what you have done."), - (6, "You will never see the end of it."), - (7, "Only darkness lies beyond."), - (10, "Goodbye, {}.") + (0, "不可避免的事情是无法逃避的。"), + (2, "你尝试过,却被发现了。"), + (5, "你所做的一切将永远不会被原谅。"), + (6, "你永远看不到结局。"), + (7, "只有黑暗在远处。"), + (10, "再见了, {}。") ] ] class HHelper: def __init__(self): - # change this to false if you want to disable + # 如果要禁用,请将其更改为false enabled = True hour = datetime.datetime.now().hour enabled = enabled and ((hour >= 20) or (hour <= 7)) From 8c271333990a781695cb97ddc4f738e01e7ac9c2 Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Sat, 23 Jan 2021 09:36:51 +0800 Subject: [PATCH 03/16] =?UTF-8?q?Signed-off-by:=20LZY2006=20=20=E5=8A=A0=E5=85=A5=E8=8B=B1=E6=96=87=E5=8E=9F?= =?UTF-8?q?=E7=89=88=20add=20origin=20English=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MANIFESTO-EN.md | 17 +++++++++++++++++ README-EN.md | 37 +++++++++++++++++++++++++++++++++++++ README.md | 2 ++ 3 files changed, 56 insertions(+) create mode 100644 MANIFESTO-EN.md create mode 100644 README-EN.md diff --git a/MANIFESTO-EN.md b/MANIFESTO-EN.md new file mode 100644 index 0000000..ab02e61 --- /dev/null +++ b/MANIFESTO-EN.md @@ -0,0 +1,17 @@ +# Manifesto +In light of recent events, I'd like to outline what this repository is for and what it isn't for. +The best way of putting it is probably as [deepfakes/faceswap's manifesto](https://github.com/deepfakes/faceswap#manifesto), edited for the sake of relevance and clarity: +> When faceswapping was first developed and published, the technology was groundbreaking, it was a huge step in AI development. It was also completely ignored outside of academia because the code was confusing and fragmentary. It required a thorough understanding of complicated AI techniques and took a lot of effort to figure it out. Until one individual brought it together into a single, cohesive collection. It ran, it worked, and as is so often the way with new technology emerging on the internet, it was immediately used to create inappropriate content. Despite the inappropriate uses the software was given originally, it was the first AI code that anyone could download, run and learn by experimentation without having a Ph.D. in math, computer theory, psychology, and more. Before "deepfakes" these techniques were like black magic, only practiced by those who could understand all of the inner workings as described in esoteric and endlessly complicated books and papers. +> +> "Deepfakes" changed all that and anyone could participate in AI development. To us, developers, the release of this code opened up a fantastic learning opportunity. It allowed us to build on ideas developed by others, collaborate with a variety of skilled coders, experiment with AI whilst learning new skills and ultimately contribute towards an emerging technology which will only see more mainstream use as it progresses. +> +> However, it became apparent to us that this may not be how others use it. Are there some people out there doing horrible things with our software? Maybe. And because of this, the developers and other contributors have been following strict ethical standards. Many of us don't even use it to create videos, we just tinker with the code to see what it does. Unfortunately, there might be people that do awful things with Yanderify's code, but they are not representative of why it was created, how we use it now, or what we see in its future. Like any technology, it can be used for good or it can be abused. It is our intention to develop Yanderify in a way that its potential for abuse is minimized whilst maximizing its potential as a tool for learning, experimenting and, yes, for legitimate faceswapping and ethical entertainment. +> +> The people that have assisted in Yanderify's development do not condone inapproriate uses of our software. We are programmers, we are engineers, we are hobbyists, but most importantly we are human beings. Yanderify was always intended for entertaining and educating. To this end, we feel that it's time to come out with a standard statement of what this software is and isn't as far as us developers are concerned. +> +> - Yanderify is not for creating inappropriate content. +> - Yanderify is not for changing faces without consent or with the intent of hiding its use. +> - Yanderify is not for any illicit, unethical, or questionable purposes. +> - Yanderify exists to experiment and discover AI techniques, for social or political commentary, for movies, and for any number of ethical and reasonable uses. +> +> We are very troubled by the fact that Yanderify can be used for unethical and disreputable things. However, we support the development of tools and techniques that can be used ethically as well as provide education and experience in AI for anyone who wants to learn it hands-on. We will take a zero tolerance approach to anyone using this software for any unethical purposes and will actively discourage any such uses. \ No newline at end of file diff --git a/README-EN.md b/README-EN.md new file mode 100644 index 0000000..dec16da --- /dev/null +++ b/README-EN.md @@ -0,0 +1,37 @@ +[First-order-wrapper is not for making unethical, illicit or inappropriate content. Learn more here.](MANIFESTO-EN.md) + +## Yanderify is now known as first-order-wrapper to more accurately describe its function. +Since this project is no longer in active development, the name won't be changed everywhere. +However, I'm starting to update documentation on all of my projects to make them better, so the name change felt neccessary. +You can still refer to the project as Yanderify, and all of the links mentioning yanderify will continue to work. Changing the repo name would destroy any bookmarks or links to here, so that is not going to happen. +The old documentation lies below. + +# first-order-wrapper +first-order-wrapper is a wrapper around [first-order-model](https://github.com/AliaksandrSiarohin/first-order-model). It exposes a simple user interface designed to be usable by anyone, with any level of technical skill. first-order-model was previously hard for the average person to use, since it required knowledge of the command line and installation of libraries. Yanderify eliminates these issues by providing a complete environment, with all necessary components bundled inside. + +Please see the "releases" tab for the latest build. The repo is not necessarily up to date. However, [the latest-v4 branch](https://github.com/dunnousername/yanderifier/tree/latest-v4) contains the latest code as of this writing, while as of this writing, master contains code from 2 major versions back. + +## What it does + +first-order-model is an Artificial Intelligence that takes a source video and an image of a face, and animates the image to match the movement of the source image. + +Here is an example of what first-order-model can do; this image was created by the [First Order Motion Model paper authors, and is taken from their repository](https://github.com/AliaksandrSiarohin/first-order-model). Most of the heavy lifting of Yanderify is done by code written by these paper authors, so I suggest you go check out their repository if you are interested. + +![Example](https://github.com/AliaksandrSiarohin/first-order-model/raw/master/sup-mat/relative-demo.gif) + +## How it works + +Double-clicking `yanderify.exe` will bring up a window that looks like this: +![Screenshot of the program](readme_mats/ss1.png) + +- "I don't have NVIDIA >=GTX750": checking this will enable CPU mode, which is a lot slower, but is the only method for users without a compatible graphics card. +- "Select Video": Clicking this will display a file selection box. This file should be the video you want to animate the new face to; in other words, this video will "drive" the image to move in the same way. +- "Select Image": This is a cropped picture of the face you want to be animated. In other words, this is the face that the video "wears". +- "Select Output": This is where your result will be stored. + +Just hit "Go," and your video will be re-animated and re-encoded with the source audio! + +## Addendum + +Join our [discord server](https://discord.gg/eEvTzRP) (updated) +A lot of people have asked for me to make a twitter. I probably won't be very active on it, but here ya go: @dunnousername2 diff --git a/README.md b/README.md index 8c137a5..a508297 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ 由 LZY 翻译为简体中文。 +[English Version 英文版本](README-EN.md) + ## Yanderify现在被称为 first-order-wrapper ,以更准确地描述其功能。 由于这个项目已不再处于开发阶段,因此不会到处更改名称。然而,我开始更新我所有项目的文档以使它们更好,因此名称的更改是必要的。您仍然可以将该项目称为Yanderify,所有提到Yanderify的链接都将继续工作。更改 repo 名称会破坏指向此处的任何书签或链接,因此不会发生这种情况。旧文件如下。 From 93601d998f80c2f522f9101f9d544fbebd76ce9c Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Sat, 23 Jan 2021 09:42:15 +0800 Subject: [PATCH 04/16] =?UTF-8?q?Signed-off-by:=20LZY2006=20=20=E9=BB=98=E8=AE=A4README=E4=BD=BF=E7=94=A8=E8=8B=B1?= =?UTF-8?q?=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MANIFESTO-EN.md | 17 ----------------- MANIFESTO-ZH.md | 17 +++++++++++++++++ MANIFESTO.md | 24 ++++++++++++------------ README-EN.md | 37 ------------------------------------- README-ZH.md | 36 ++++++++++++++++++++++++++++++++++++ README.md | 47 +++++++++++++++++++++++++---------------------- 6 files changed, 90 insertions(+), 88 deletions(-) delete mode 100644 MANIFESTO-EN.md create mode 100644 MANIFESTO-ZH.md delete mode 100644 README-EN.md create mode 100644 README-ZH.md diff --git a/MANIFESTO-EN.md b/MANIFESTO-EN.md deleted file mode 100644 index ab02e61..0000000 --- a/MANIFESTO-EN.md +++ /dev/null @@ -1,17 +0,0 @@ -# Manifesto -In light of recent events, I'd like to outline what this repository is for and what it isn't for. -The best way of putting it is probably as [deepfakes/faceswap's manifesto](https://github.com/deepfakes/faceswap#manifesto), edited for the sake of relevance and clarity: -> When faceswapping was first developed and published, the technology was groundbreaking, it was a huge step in AI development. It was also completely ignored outside of academia because the code was confusing and fragmentary. It required a thorough understanding of complicated AI techniques and took a lot of effort to figure it out. Until one individual brought it together into a single, cohesive collection. It ran, it worked, and as is so often the way with new technology emerging on the internet, it was immediately used to create inappropriate content. Despite the inappropriate uses the software was given originally, it was the first AI code that anyone could download, run and learn by experimentation without having a Ph.D. in math, computer theory, psychology, and more. Before "deepfakes" these techniques were like black magic, only practiced by those who could understand all of the inner workings as described in esoteric and endlessly complicated books and papers. -> -> "Deepfakes" changed all that and anyone could participate in AI development. To us, developers, the release of this code opened up a fantastic learning opportunity. It allowed us to build on ideas developed by others, collaborate with a variety of skilled coders, experiment with AI whilst learning new skills and ultimately contribute towards an emerging technology which will only see more mainstream use as it progresses. -> -> However, it became apparent to us that this may not be how others use it. Are there some people out there doing horrible things with our software? Maybe. And because of this, the developers and other contributors have been following strict ethical standards. Many of us don't even use it to create videos, we just tinker with the code to see what it does. Unfortunately, there might be people that do awful things with Yanderify's code, but they are not representative of why it was created, how we use it now, or what we see in its future. Like any technology, it can be used for good or it can be abused. It is our intention to develop Yanderify in a way that its potential for abuse is minimized whilst maximizing its potential as a tool for learning, experimenting and, yes, for legitimate faceswapping and ethical entertainment. -> -> The people that have assisted in Yanderify's development do not condone inapproriate uses of our software. We are programmers, we are engineers, we are hobbyists, but most importantly we are human beings. Yanderify was always intended for entertaining and educating. To this end, we feel that it's time to come out with a standard statement of what this software is and isn't as far as us developers are concerned. -> -> - Yanderify is not for creating inappropriate content. -> - Yanderify is not for changing faces without consent or with the intent of hiding its use. -> - Yanderify is not for any illicit, unethical, or questionable purposes. -> - Yanderify exists to experiment and discover AI techniques, for social or political commentary, for movies, and for any number of ethical and reasonable uses. -> -> We are very troubled by the fact that Yanderify can be used for unethical and disreputable things. However, we support the development of tools and techniques that can be used ethically as well as provide education and experience in AI for anyone who wants to learn it hands-on. We will take a zero tolerance approach to anyone using this software for any unethical purposes and will actively discourage any such uses. \ No newline at end of file diff --git a/MANIFESTO-ZH.md b/MANIFESTO-ZH.md new file mode 100644 index 0000000..0a47181 --- /dev/null +++ b/MANIFESTO-ZH.md @@ -0,0 +1,17 @@ +# 宣言 +鉴于最近发生的事件,我想概述一下该存储库的用途和目的。 +最好的表达方式可能是 [Deepfakes/faceswap宣言(英文)](https://github.com/deepfakes/faceswap#manifesto) ,为了相关性和明确性而进行了编辑: +> 当Faceswapping(换脸)最初被开发和发布时,该技术是开创性的,这是AI开发的一大步。 在学术界之外,它也被完全忽略了,因为该代码令人困惑且零碎。 它需要对复杂的AI技术有透彻的了解,并花了很多精力才能弄清楚。 直到一个人将其汇集成一个单一的,有凝聚力的集合。 它运行,运行,而且是如此频繁的方式与新技术出现在互联网上,它立即被用于创建不合适的内容。 尽管最开始就有人用于不适当的目的,这还是第一个任何人都可以下载、运行和通过实验学习的人工智能代码,而无需拥有数学、计算机理论、心理学等方面的博士学位。 在“深造”之前,这些技术就像是黑魔法,只有那些了解深奥且无穷无尽的书籍和论文中所描述的所有内部工作原理的人才能实践。 +> +> “ Deepfakes”改变了这一切,任何人都可以参与AI开发。 对于我们开发人员而言,此代码的发布带来了绝佳的学习机会。 它使我们能够借鉴其他人提出的想法,与各种熟练写代码的人员合作,在学习新技能的同时尝试AI,并最终为新兴技术做出贡献,随着技术的进步,它只会在更多的主流场合得到使用。 +> +> 但是,对我们来说很明显,这可能不是别人使用它的方式。 有人在用我们的软件做可怕的事情吗? 也许。 因此,开发人员和其他贡献者一直遵循严格的道德标准。 我们许多人甚至不使用它来创建视频,我们只是修改代码,看看它能做什么。 不幸的是,可能有人用Yanderify的代码做了可怕的事情,但是它们并不能代表创建它的原因,我们现在的使用方式或我们对代码的未来的看法。像任何技术一样,它可以被用来做好事,也可以被滥用。 我们的目的是开发Yanderify,以最大程度地减少其滥用的可能性,同时最大程度地发挥其作为学习,实验以及正当的换脸和道德娱乐的工具的潜力。 +> +> 帮助Yanderify开发的人不会容忍对我们软件的不当使用。我们是程序员,我们是工程师,我们是业余爱好者,但最重要的是我们是人。Yanderify始终旨在娱乐和教育。为此,我们认为是时候就该软件的含义和对我们开发人员而言 不甚明确 的问题发表标准声明了。 +> +> - Yanderify 不是为了创造不适当的内容。 +> - Yanderify 禁止未经同意或出于隐瞒使用目的而更改面孔。 +> - Yanderify 不是为了任何非法,不道德或可疑目的。 +> - Yanderify 的存在是为了试验和发现AI技术,进行社会或政治评论(请不要在中国大陆这么做),电影以及各种道德和合理用途的实验。 +> +> 我们非常不安的事实是, Yandrify 可以用于不道德和不名誉的事情。然而,我们支持开发可合乎道德使用的工具和技术,并为任何想亲自学习人工智能的人提供人工智能方面的教育和经验。对于出于任何不道德目的而使用此软件的任何人,我们将采取零容忍的态度,并将积极劝阻任何此类使用。 \ No newline at end of file diff --git a/MANIFESTO.md b/MANIFESTO.md index 0a47181..ab02e61 100644 --- a/MANIFESTO.md +++ b/MANIFESTO.md @@ -1,17 +1,17 @@ -# 宣言 -鉴于最近发生的事件,我想概述一下该存储库的用途和目的。 -最好的表达方式可能是 [Deepfakes/faceswap宣言(英文)](https://github.com/deepfakes/faceswap#manifesto) ,为了相关性和明确性而进行了编辑: -> 当Faceswapping(换脸)最初被开发和发布时,该技术是开创性的,这是AI开发的一大步。 在学术界之外,它也被完全忽略了,因为该代码令人困惑且零碎。 它需要对复杂的AI技术有透彻的了解,并花了很多精力才能弄清楚。 直到一个人将其汇集成一个单一的,有凝聚力的集合。 它运行,运行,而且是如此频繁的方式与新技术出现在互联网上,它立即被用于创建不合适的内容。 尽管最开始就有人用于不适当的目的,这还是第一个任何人都可以下载、运行和通过实验学习的人工智能代码,而无需拥有数学、计算机理论、心理学等方面的博士学位。 在“深造”之前,这些技术就像是黑魔法,只有那些了解深奥且无穷无尽的书籍和论文中所描述的所有内部工作原理的人才能实践。 +# Manifesto +In light of recent events, I'd like to outline what this repository is for and what it isn't for. +The best way of putting it is probably as [deepfakes/faceswap's manifesto](https://github.com/deepfakes/faceswap#manifesto), edited for the sake of relevance and clarity: +> When faceswapping was first developed and published, the technology was groundbreaking, it was a huge step in AI development. It was also completely ignored outside of academia because the code was confusing and fragmentary. It required a thorough understanding of complicated AI techniques and took a lot of effort to figure it out. Until one individual brought it together into a single, cohesive collection. It ran, it worked, and as is so often the way with new technology emerging on the internet, it was immediately used to create inappropriate content. Despite the inappropriate uses the software was given originally, it was the first AI code that anyone could download, run and learn by experimentation without having a Ph.D. in math, computer theory, psychology, and more. Before "deepfakes" these techniques were like black magic, only practiced by those who could understand all of the inner workings as described in esoteric and endlessly complicated books and papers. > -> “ Deepfakes”改变了这一切,任何人都可以参与AI开发。 对于我们开发人员而言,此代码的发布带来了绝佳的学习机会。 它使我们能够借鉴其他人提出的想法,与各种熟练写代码的人员合作,在学习新技能的同时尝试AI,并最终为新兴技术做出贡献,随着技术的进步,它只会在更多的主流场合得到使用。 +> "Deepfakes" changed all that and anyone could participate in AI development. To us, developers, the release of this code opened up a fantastic learning opportunity. It allowed us to build on ideas developed by others, collaborate with a variety of skilled coders, experiment with AI whilst learning new skills and ultimately contribute towards an emerging technology which will only see more mainstream use as it progresses. > -> 但是,对我们来说很明显,这可能不是别人使用它的方式。 有人在用我们的软件做可怕的事情吗? 也许。 因此,开发人员和其他贡献者一直遵循严格的道德标准。 我们许多人甚至不使用它来创建视频,我们只是修改代码,看看它能做什么。 不幸的是,可能有人用Yanderify的代码做了可怕的事情,但是它们并不能代表创建它的原因,我们现在的使用方式或我们对代码的未来的看法。像任何技术一样,它可以被用来做好事,也可以被滥用。 我们的目的是开发Yanderify,以最大程度地减少其滥用的可能性,同时最大程度地发挥其作为学习,实验以及正当的换脸和道德娱乐的工具的潜力。 +> However, it became apparent to us that this may not be how others use it. Are there some people out there doing horrible things with our software? Maybe. And because of this, the developers and other contributors have been following strict ethical standards. Many of us don't even use it to create videos, we just tinker with the code to see what it does. Unfortunately, there might be people that do awful things with Yanderify's code, but they are not representative of why it was created, how we use it now, or what we see in its future. Like any technology, it can be used for good or it can be abused. It is our intention to develop Yanderify in a way that its potential for abuse is minimized whilst maximizing its potential as a tool for learning, experimenting and, yes, for legitimate faceswapping and ethical entertainment. > -> 帮助Yanderify开发的人不会容忍对我们软件的不当使用。我们是程序员,我们是工程师,我们是业余爱好者,但最重要的是我们是人。Yanderify始终旨在娱乐和教育。为此,我们认为是时候就该软件的含义和对我们开发人员而言 不甚明确 的问题发表标准声明了。 +> The people that have assisted in Yanderify's development do not condone inapproriate uses of our software. We are programmers, we are engineers, we are hobbyists, but most importantly we are human beings. Yanderify was always intended for entertaining and educating. To this end, we feel that it's time to come out with a standard statement of what this software is and isn't as far as us developers are concerned. > -> - Yanderify 不是为了创造不适当的内容。 -> - Yanderify 禁止未经同意或出于隐瞒使用目的而更改面孔。 -> - Yanderify 不是为了任何非法,不道德或可疑目的。 -> - Yanderify 的存在是为了试验和发现AI技术,进行社会或政治评论(请不要在中国大陆这么做),电影以及各种道德和合理用途的实验。 +> - Yanderify is not for creating inappropriate content. +> - Yanderify is not for changing faces without consent or with the intent of hiding its use. +> - Yanderify is not for any illicit, unethical, or questionable purposes. +> - Yanderify exists to experiment and discover AI techniques, for social or political commentary, for movies, and for any number of ethical and reasonable uses. > -> 我们非常不安的事实是, Yandrify 可以用于不道德和不名誉的事情。然而,我们支持开发可合乎道德使用的工具和技术,并为任何想亲自学习人工智能的人提供人工智能方面的教育和经验。对于出于任何不道德目的而使用此软件的任何人,我们将采取零容忍的态度,并将积极劝阻任何此类使用。 \ No newline at end of file +> We are very troubled by the fact that Yanderify can be used for unethical and disreputable things. However, we support the development of tools and techniques that can be used ethically as well as provide education and experience in AI for anyone who wants to learn it hands-on. We will take a zero tolerance approach to anyone using this software for any unethical purposes and will actively discourage any such uses. \ No newline at end of file diff --git a/README-EN.md b/README-EN.md deleted file mode 100644 index dec16da..0000000 --- a/README-EN.md +++ /dev/null @@ -1,37 +0,0 @@ -[First-order-wrapper is not for making unethical, illicit or inappropriate content. Learn more here.](MANIFESTO-EN.md) - -## Yanderify is now known as first-order-wrapper to more accurately describe its function. -Since this project is no longer in active development, the name won't be changed everywhere. -However, I'm starting to update documentation on all of my projects to make them better, so the name change felt neccessary. -You can still refer to the project as Yanderify, and all of the links mentioning yanderify will continue to work. Changing the repo name would destroy any bookmarks or links to here, so that is not going to happen. -The old documentation lies below. - -# first-order-wrapper -first-order-wrapper is a wrapper around [first-order-model](https://github.com/AliaksandrSiarohin/first-order-model). It exposes a simple user interface designed to be usable by anyone, with any level of technical skill. first-order-model was previously hard for the average person to use, since it required knowledge of the command line and installation of libraries. Yanderify eliminates these issues by providing a complete environment, with all necessary components bundled inside. - -Please see the "releases" tab for the latest build. The repo is not necessarily up to date. However, [the latest-v4 branch](https://github.com/dunnousername/yanderifier/tree/latest-v4) contains the latest code as of this writing, while as of this writing, master contains code from 2 major versions back. - -## What it does - -first-order-model is an Artificial Intelligence that takes a source video and an image of a face, and animates the image to match the movement of the source image. - -Here is an example of what first-order-model can do; this image was created by the [First Order Motion Model paper authors, and is taken from their repository](https://github.com/AliaksandrSiarohin/first-order-model). Most of the heavy lifting of Yanderify is done by code written by these paper authors, so I suggest you go check out their repository if you are interested. - -![Example](https://github.com/AliaksandrSiarohin/first-order-model/raw/master/sup-mat/relative-demo.gif) - -## How it works - -Double-clicking `yanderify.exe` will bring up a window that looks like this: -![Screenshot of the program](readme_mats/ss1.png) - -- "I don't have NVIDIA >=GTX750": checking this will enable CPU mode, which is a lot slower, but is the only method for users without a compatible graphics card. -- "Select Video": Clicking this will display a file selection box. This file should be the video you want to animate the new face to; in other words, this video will "drive" the image to move in the same way. -- "Select Image": This is a cropped picture of the face you want to be animated. In other words, this is the face that the video "wears". -- "Select Output": This is where your result will be stored. - -Just hit "Go," and your video will be re-animated and re-encoded with the source audio! - -## Addendum - -Join our [discord server](https://discord.gg/eEvTzRP) (updated) -A lot of people have asked for me to make a twitter. I probably won't be very active on it, but here ya go: @dunnousername2 diff --git a/README-ZH.md b/README-ZH.md new file mode 100644 index 0000000..115a017 --- /dev/null +++ b/README-ZH.md @@ -0,0 +1,36 @@ +[First-order-wrapper不是为了制作不道德,非法或不适当的内容。 在这里了解更多。](MANIFESTO-ZH.md) + +由 LZY 翻译为简体中文。 + +[English Version 英文版本](README-EN.md) + +## Yanderify现在被称为 first-order-wrapper ,以更准确地描述其功能。 +由于这个项目已不再处于开发阶段,因此不会到处更改名称。然而,我开始更新我所有项目的文档以使它们更好,因此名称的更改是必要的。您仍然可以将该项目称为Yanderify,所有提到Yanderify的链接都将继续工作。更改 repo 名称会破坏指向此处的任何书签或链接,因此不会发生这种情况。旧文件如下。 + +# first-order-wrapper +first-order-wrapper 是围绕 [first-order-model](https://github.com/AliaksandrSiarohin/first-order-model) 的包装器。它公开了一个简单的用户界面,设计成任何人都可以使用,任何技术水平。 first-order-model 以前很难被普通人使用,因为它需要命令行和库的安装知识。Yanderify通过提供一个完整的环境消除了这些问题,并将所有必要的组件捆绑在其中。 + +有关最新版本,请参见“版本”选项卡。回购不一定是最新的。但是,[latest-v4 分支](https://github.com/dunnousername/yanderifier/tree/latest-v4)包含了本文撰写时的最新代码,而master则包含了后面两个主要版本的代码。 + +## 它能做什么 + +下面是first-order-model可以做什么的一个例子;这个图像是由 [First Order Motion Model论文的作者创建的,并且是从他们的存储库中获取的。](https://github.com/AliaksandrSiarohin/first-order-model)Yanderify的大部分繁重工作都是由这些论文作者编写的代码完成的,因此如果您感兴趣,我建议您去查看他们的存储库。 + +![例子(在中国大陆可能无法显示)](https://github.com/AliaksandrSiarohin/first-order-model/raw/master/sup-mat/relative-demo.gif) + +## 工作原理 + +双击 `yanderify.exe` yanderify.exe将弹出一个看起来像这样的窗口: +![程序截图(在中国大陆可能无法显示)](readme_mats/ss1.png) + +- “我没有 >=GTX750 的NVIDIA显卡”:选中此选项将启用CPU模式,这会慢很多,但对于没有兼容图形卡的用户来说,这是唯一的方法。 +- “选择视频”:单击此将显示文件选择框。 该文件应该是您想要为新面孔设置动画的视频; 换句话说,该视频将“驱动”图像以相同的方式移动。 +- “选择图像”:这是要设置动画的人脸的裁剪图片。换句话说,这就是视频“穿”的脸。 +- “选择输出”:这是存储结果的位置。 + +只需点击“开始”,您的视频就会重新设置动画,并用源音频重新编码! + +## 附录 + +加入我们的 [discord服务器(在中国大陆可能无法访问)](https://discord.gg/eEvTzRP) (已更新) +很多人都要求我发Twitter。 我可能不会非常活跃,但是在这里:@dunnousername2(在中国大陆可能无法访问) diff --git a/README.md b/README.md index a508297..ea586cb 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,39 @@ -[First-order-wrapper不是为了制作不道德,非法或不适当的内容。 在这里了解更多。](MANIFESTO.md) +[First-order-wrapper is not for making unethical, illicit or inappropriate content. Learn more here.](MANIFESTO.md) -由 LZY 翻译为简体中文。 +[Simplified Chinese version 简体中文版本](README-ZH.md) -[English Version 英文版本](README-EN.md) - -## Yanderify现在被称为 first-order-wrapper ,以更准确地描述其功能。 -由于这个项目已不再处于开发阶段,因此不会到处更改名称。然而,我开始更新我所有项目的文档以使它们更好,因此名称的更改是必要的。您仍然可以将该项目称为Yanderify,所有提到Yanderify的链接都将继续工作。更改 repo 名称会破坏指向此处的任何书签或链接,因此不会发生这种情况。旧文件如下。 +## Yanderify is now known as first-order-wrapper to more accurately describe its function. +Since this project is no longer in active development, the name won't be changed everywhere. +However, I'm starting to update documentation on all of my projects to make them better, so the name change felt neccessary. +You can still refer to the project as Yanderify, and all of the links mentioning yanderify will continue to work. Changing the repo name would destroy any bookmarks or links to here, so that is not going to happen. +The old documentation lies below. # first-order-wrapper -first-order-wrapper 是围绕 [first-order-model](https://github.com/AliaksandrSiarohin/first-order-model) 的包装器。它公开了一个简单的用户界面,设计成任何人都可以使用,任何技术水平。 first-order-model 以前很难被普通人使用,因为它需要命令行和库的安装知识。Yanderify通过提供一个完整的环境消除了这些问题,并将所有必要的组件捆绑在其中。 +first-order-wrapper is a wrapper around [first-order-model](https://github.com/AliaksandrSiarohin/first-order-model). It exposes a simple user interface designed to be usable by anyone, with any level of technical skill. first-order-model was previously hard for the average person to use, since it required knowledge of the command line and installation of libraries. Yanderify eliminates these issues by providing a complete environment, with all necessary components bundled inside. + +Please see the "releases" tab for the latest build. The repo is not necessarily up to date. However, [the latest-v4 branch](https://github.com/dunnousername/yanderifier/tree/latest-v4) contains the latest code as of this writing, while as of this writing, master contains code from 2 major versions back. -有关最新版本,请参见“版本”选项卡。回购不一定是最新的。但是,[latest-v4 分支](https://github.com/dunnousername/yanderifier/tree/latest-v4)包含了本文撰写时的最新代码,而master则包含了后面两个主要版本的代码。 +## What it does -## 它能做什么 +first-order-model is an Artificial Intelligence that takes a source video and an image of a face, and animates the image to match the movement of the source image. -下面是first-order-model可以做什么的一个例子;这个图像是由 [First Order Motion Model论文的作者创建的,并且是从他们的存储库中获取的。](https://github.com/AliaksandrSiarohin/first-order-model)Yanderify的大部分繁重工作都是由这些论文作者编写的代码完成的,因此如果您感兴趣,我建议您去查看他们的存储库。 +Here is an example of what first-order-model can do; this image was created by the [First Order Motion Model paper authors, and is taken from their repository](https://github.com/AliaksandrSiarohin/first-order-model). Most of the heavy lifting of Yanderify is done by code written by these paper authors, so I suggest you go check out their repository if you are interested. -![例子(在中国大陆可能无法显示)](https://github.com/AliaksandrSiarohin/first-order-model/raw/master/sup-mat/relative-demo.gif) +![Example](https://github.com/AliaksandrSiarohin/first-order-model/raw/master/sup-mat/relative-demo.gif) -## 工作原理 +## How it works -双击 `yanderify.exe` yanderify.exe将弹出一个看起来像这样的窗口: -![程序截图(在中国大陆可能无法显示)](readme_mats/ss1.png) +Double-clicking `yanderify.exe` will bring up a window that looks like this: +![Screenshot of the program](readme_mats/ss1.png) -- “我没有 >=GTX750 的NVIDIA显卡”:选中此选项将启用CPU模式,这会慢很多,但对于没有兼容图形卡的用户来说,这是唯一的方法。 -- “选择视频”:单击此将显示文件选择框。 该文件应该是您想要为新面孔设置动画的视频; 换句话说,该视频将“驱动”图像以相同的方式移动。 -- “选择图像”:这是要设置动画的人脸的裁剪图片。换句话说,这就是视频“穿”的脸。 -- “选择输出”:这是存储结果的位置。 +- "I don't have NVIDIA >=GTX750": checking this will enable CPU mode, which is a lot slower, but is the only method for users without a compatible graphics card. +- "Select Video": Clicking this will display a file selection box. This file should be the video you want to animate the new face to; in other words, this video will "drive" the image to move in the same way. +- "Select Image": This is a cropped picture of the face you want to be animated. In other words, this is the face that the video "wears". +- "Select Output": This is where your result will be stored. -只需点击“开始”,您的视频就会重新设置动画,并用源音频重新编码! +Just hit "Go," and your video will be re-animated and re-encoded with the source audio! -## 附录 +## Addendum -加入我们的 [discord服务器(在中国大陆可能无法访问)](https://discord.gg/eEvTzRP) (已更新) -很多人都要求我发Twitter。 我可能不会非常活跃,但是在这里:@dunnousername2(在中国大陆可能无法访问) +Join our [discord server](https://discord.gg/eEvTzRP) (updated) +A lot of people have asked for me to make a twitter. I probably won't be very active on it, but here ya go: @dunnousername2 From 3d3950787b0f08d88a9a9d1fc62c6ee1ccb35e0b Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Sat, 23 Jan 2021 11:12:45 +0800 Subject: [PATCH 05/16] =?UTF-8?q?Signed-off-by:=20LZY2006=20=20=E5=A2=9E=E5=8A=A0=E4=B8=AD=E6=96=87=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/yanderify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yanderify/yanderify.py b/yanderify/yanderify.py index 9d80455..5fde216 100644 --- a/yanderify/yanderify.py +++ b/yanderify/yanderify.py @@ -1,5 +1,5 @@ # coding: utf-8 -print("Loading...") +print("加载中……") import hhelper import warnings From df56b4ad578a01af6cad2728732036782056564e Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 13:20:01 +0800 Subject: [PATCH 06/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E4=B8=AD?= =?UTF-8?q?=E8=8B=B1=E5=8F=8C=E8=AF=AD=E8=AF=AD=E8=A8=80=E5=8C=85=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/languages.json | 233 +++++++++++++++++++++++++++++++++++++++ yanderify/yanderify.py | 101 +++++++++-------- 2 files changed, 289 insertions(+), 45 deletions(-) create mode 100644 yanderify/languages.json diff --git a/yanderify/languages.json b/yanderify/languages.json new file mode 100644 index 0000000..bc83f12 --- /dev/null +++ b/yanderify/languages.json @@ -0,0 +1,233 @@ +{ + "loading": + { + "english" : "Loading...", + "chinese" : "加载中..." + }, + "new_video_input_path" : + { + "english" : "New video input path: {}", + "chinese" : "新视频输入路径: {}" + }, + "new_image_input_path" : + { + "english" : "New image input path: {}", + "chinese" : "新图像输入路径: {}" + }, + "err_msg_1": + { + "english" : "This section contains the details the devs need to fix this issue.", + "chinese" : "本节包含开发人员修复此问题所需的详细信息。" + }, + "err_msg_2": + { + "english" : "If you are reporting a bug, please include this entire section.", + "chinese" : "如果您要报告BUG,请报告整个部分。" + }, + "err_msg_3": + { + "english" : "If you leave out any of it, there is a good chance the devs will not be able to help.", + "chinese" : "如果您忽略了其中任何部分,开发人员很有可能将无法提供帮助。" + }, + "err_msg_4": + { + "english" : "Error: received a {} at stage \"{}\".", + "chinese" : "错误: 接收到了 {} 在阶段 \"{}\"。" + }, + "err_msg_5": + { + "english" : "Message: \"{}\"", + "chinese" : "信息: \"{}\"" + }, + "err_msg_6": + { + "english" : "Full traceback:", + "chinese" : "完整的异常信息:" + }, + "err_msg_7": + { + "english" : "This is the last line of the crash report section.", + "chinese" : "崩溃报告部分结束。" + }, + "reloading_checkpoints" : + { + "english" : "Reloading checkpoints...", + "chinese" : "加载模型..." + }, + "finished_loading_checkpoints" : + { + "english" : "Finished reloading checkpoints", + "chinese" : "加载完成" + }, + "loading_sources" : + { + "english" : "Loading sources...", + "chinese" : "加载资源..." + }, + "sources_loaded" : + { + "english" : "Sources loaded", + "chinese" : "资源已载入" + }, + "writing_output_to_file" : + { + "english" : "Writing output to file...", + "chinese" : "正在将输入写入文件..." + }, + "muxing_audio_streams_into_output_file": + { + "english" : "Muxing audio streams into output file...", + "chinese" : "正在整合音频到输出文件..." + }, + "suberr1": + { + "english" : "ffmpeg crashed!", + "chinese" : "ffmpeg崩溃了!" + }, + "suberr2": + { + "english" : "usually this means the deepfake process worked, but re-encoding failed.", + "chinese" : "通常,这意味着主要进程有效,但是重新编码失败。" + }, + "suberr3": + { + "english" : "you can attempt to salvage your progress by re-muxing audio streams manually.", + "chinese" : "您可以尝试通过手动重新混合音频流。" + }, + "suberr4": + { + "english" : "this may also happen if your input video contains no audio; if this is the case, the file should be at least mostly intact.", + "chinese" : "如果您输入的视频不包含音频,也会发生这种情况; 如果是这种情况,该文件至少应保持完整。" + }, + "othererr1": + { + "english" : "yanderify crashed!", + "chinese" : "一些常规问题:" + }, + "othererr2": + { + "english" : "- you have an AMD card. AMD cards are not supported in GPU mode for technical reasons. However, you can run in CPU mode, albeit much lower. Please read the disclaimer at the top about CPUs!", + "chinese" : "- 你有一张AMD显卡. AMD卡因为一些技术原因不在GPU模式中被支持。然而, 你可以用CPU模式运行,尽管会慢.请阅读在顶部关于CPU的说明!" + }, + "othererr3": + { + "english" : "- you have an NVIDIA card, but there is either not enough VRAM or the card is too old. >=700-series cards with >=2GB dedicated VRAM should work fine", + "chinese" : "- 你有一张Nvidia的显卡,不过没有足够的内存或者型号太老了。新于或等于700-系卡 和大于等于2GB专用显示内存可以正常工作" + }, + "othererr4": + { + "english" : "- you have a working card, but there is not enough available VRAM to run the deepfake process. Browsers commonly cause VRAM issues. If you have any games open, try closing them.", + "chinese" : "- 你又可以正常工作的卡, 但没有足够的空闲的显存来运行DeepFake。浏览器经常导致显存问题。如果你后台打开了游戏,请退出游戏。" + }, + "othererr5": + { + "english" : "- one of the devs fucked up somewhere. if that is the case, make sure to submit the full crash report (you might have to scroll up!), otherwise we cannot help you!", + "chinese" : "- 有个开发者日了狗了. 如果是这样, 确保提交完整的崩溃日志 (你可能得向上滑!), 除此之外我们帮不了你!" + }, + "othererr6": + { + "english" : "yanderify crashed!", + "chinese" : "yanderify崩溃了!" + }, + "keyboardinterrupt": + { + "english" : "Stopping...", + "chinese" : "正在停止..." + }, + "success": + { + "english" : "success!", + "chinese" : "成功!" + }, + "start1": + { + "english" : "starting...", + "chinese" : "启动中..." + }, + "start2": + { + "english" : "error: files must be selected", + "chinese" : "错误:必须选择文件" + }, + "start3": + { + "english" : "error: already started!", + "chinese" : "错误:已经启动了!" + }, + "class1": + { + "english" : "I don't have NVIDIA >=GTX750", + "chinese" : "我没有 >=GTX750 的NVIDIA显卡" + }, + "class2": + { + "english" : "Select Video", + "chinese" : "选择视频" + }, + "class3": + { + "english" : "Select Image", + "chinese" : "选择图片" + }, + "class4": + { + "english" : "Select Output", + "chinese" : "选择输出位置" + }, + "class5": + { + "english" : "∞ kitties", + "chinese" : "无限猫图" + }, + "class6": + { + "english" : "Go", + "chinese" : "开始" + }, + "class7": + { + "english" : "Started Yanderify 3.0.6-alpha-0", + "chinese" : "启动了Yanderify 3.0.6-alpha-0" + }, + "class8": + { + "english" : "Warning: This is not a stable release and should not be treated as such.", + "chinese" : "警告: 这不是一个稳定版。" + }, + "class9": + { + "english" : "Disclaimer: CPU mode on low-end computers or most laptops generally will cause the system to lock-up.", + "chinese" : "说明: CPU模式在低端电脑或大多数笔记本上通常会导致系统供电不足断电." + }, + "class10": + { + "english" : "We are not liable if you freeze your PC by refusing to listen to this advice.", + "chinese" : "如果您通过拒绝听取此建议而电脑被损坏,我们将不承担任何责任。" + }, + "class11": + { + "english" : "Written by dunnousername#8672.", + "chinese" : "dunnousername#8672写的." + }, + "class12": + { + "english" : "heavily inspired by windy's efforts", + "chinese" : "深受 windy 的启发" + }, + "class13": + { + "english" : "Toggle advanced settings", + "chinese" : "切换高级选项" + }, + "class14": + { + "english" : "Go", + "chinese" : "开始" + }, + "class15": + { + "english" : "Stop", + "chinese" : "停止" + } + +} \ No newline at end of file diff --git a/yanderify/yanderify.py b/yanderify/yanderify.py index 5fde216..583bfe6 100644 --- a/yanderify/yanderify.py +++ b/yanderify/yanderify.py @@ -1,10 +1,21 @@ # coding: utf-8 -print("加载中……") import hhelper import warnings import sys +import locale +sys_language = locale.getdefaultlocale() +if "zh" in sys_language[0]: + sys_language = "chinese" +else: + sys_language = "english" +import json +with open("languages.json", "r", encoding="utf-8") as f: + languages = json.load(f) + +print(languages["loading"][sys_language]) + if 'debug' not in sys.argv: warnings.simplefilter('ignore') @@ -98,7 +109,7 @@ def video_in_cb(): if x is not None: if len(x) > 0: video_in_path = x - write('新视频输入路径: {}'.format(video_in_path)) + write(languages["new_video_input_path"][sys_language].format(video_in_path)) def image_in_cb(): global image_in_path @@ -106,7 +117,7 @@ def image_in_cb(): if x is not None: if len(x) > 0: image_in_path = x - write('新图像输入路径: {}'.format(image_in_path)) + write(languages["new_image_input_path"][sys_language].format(image_in_path)) def video_out_cb(): global video_out_path @@ -122,12 +133,12 @@ def trace(stage, inputs, aux=None): sep = '===========================' (type_, value, tb) = sys.exc_info() q.put(sep) - q.put('本节包含开发人员修复此问题所需的详细信息。') - q.put('如果您要报告错误,请包括整个部分。') - q.put('如果您忽略了其中任何一个,开发人员很有可能将无法提供帮助。') - q.put('错误: 接收到了 {} 在阶段 "{}".'.format(type_.__name__, stage)) - q.put('信息: "{}"'.format(str(value))) - q.put('完整的异常信息:') + q.put(languages["err_msg_1"][sys_language]) + q.put(languages["err_msg_2"][sys_language]) + q.put(languages["err_msg_3"][sys_language]) + q.put(languages["err_msg_4"][sys_language].format(type_.__name__, stage)) + q.put(languages["err_msg_5"][sys_language].format(str(value))) + q.put(languages["err_msg_6"][sys_language]) for s in traceback.format_tb(tb): q.put(s) q.put('') @@ -136,7 +147,7 @@ def trace(stage, inputs, aux=None): q.put('') q.put(inputs) q.put('') - q.put('这是崩溃报告部分的最后一行。') + q.put(languages["err_msg_7"][sys_language]) q.put(sep) def acceptable_resolution(x, y): @@ -193,13 +204,13 @@ def worker_thread(vid0n, img0n, vid1n, cpu, relative): global checkpoints with run_lock: if not (cpu == checkpoints['cpu']): - q.put('重新加载存档点...') + q.put(languages["reloading_checkpoints"][sys_language]) checkpoints['cpu'] = cpu reload() - q.put('重新加载存档点完成') + q.put(languages["finished_loading_checkpoints"][sys_language]) if os.path.isfile('tmp.mp4'): os.remove('tmp.mp4') - q.put('加载资源...') + q.put(languages["loading_sources"][sys_language]) vid0r = imageio.get_reader(vid0n) fps = vid0r.get_meta_data()['fps'] vid0 = [] @@ -219,13 +230,13 @@ def worker_thread(vid0n, img0n, vid1n, cpu, relative): size = acceptable_resolution(size[0], size[1]) img0 = resize(img0, (256, 256))[..., :3] vid1 = imageio.get_writer('tmp.mp4', fps=fps) - q.put('资源已载入') + q.put(languages["sources_loaded"][sys_language]) for frame in make_animation_modified(img0, iter(vid0), checkpoints['g'], checkpoints['kp'], cpu=cpu, relative=relative): vid1.append_data(img_as_ubyte(resize(frame, size))) progress += 1 - print('正在将输入写入文件...') + print(languages["writing_output_to_file"][sys_language]) vid1.close() - q.put('正在整合音频到输出文件...') + q.put(languages["muxing_audio_streams_into_output_file"][sys_language]) cmd = shlex.split('ffmpeg -y -hide_banner -loglevel warning -i tmp.mp4 -i') cmd.append(vid0n) cmd.extend(shlex.split('-map 0:v -map 1:a -movflags faststart -c:v libx264 -pix_fmt yuv420p -x264-params "nal-hrd=cbr" -b:v 1200K -minrate 1200K -maxrate 1200K -bufsize 2M')) @@ -242,26 +253,26 @@ def worker_thread(vid0n, img0n, vid1n, cpu, relative): e.output ) trace('ffmpeg', [vid0n, img0n, vid1n], aux=msg) - q.put('ffmpeg崩溃了!') - q.put('通常,这意味着深度伪造进程有效,但是重新编码失败。') + q.put(languages["suberr1"][sys_language]) + q.put(languages["suberr2"][sys_language]) shutil.copy('tmp.mp4', vid1n) - q.put('您可以尝试通过手动重新混合音频流来挽救进度.') - q.put('如果您输入的视频不包含音频,也会发生这种情况; 如果是这种情况,该文件至少应保持完整。') + q.put(languages["suberr3"][sys_language]) + q.put(languages["suberr4"][sys_language]) raise e except Exception as e: msg = 'cpu={}'.format(cpu) trace('predict', [vid0n, img0n, vid1n], aux=msg) - q.put('yanderify崩溃了!') - q.put('一些常规问题:') - q.put('- 你有一张AMD显卡. AMD卡因为一些技术原因不在GPU模式中被支持。然而, 你可以用CPU模式运行,尽管会慢.请阅读在顶部关于CPU的说明!') - q.put('- 你有一张Nvidia的显卡, 不过没有足够的内存或者型号太老了. 新于或等于700-系卡 和大于等于2GB专用显示内存可以正常工作') - q.put('- 你又可以正常工作的卡, 但没有足够的空闲的显存来运行深度伪造. 浏览器经常导致显存问题. 如果你有任何打开的游戏,关掉他们.') - q.put('- 有个开发者日了狗了. 如果是这样, 确保提交完整的崩溃日志 (你可能得向上滑!), 除此之外我们帮不了你!') + q.put(languages["othererr1"][sys_language]) + q.put(languages["othererr2"][sys_language]) + q.put(languages["othererr3"][sys_language]) + q.put(languages["othererr4"][sys_language]) + q.put(languages["othererr5"][sys_language]) + q.put(languages["othererr6"][sys_language]) raise e except KeyboardInterrupt as e: - q.put('正在停止...') + q.put(languages["keyboardinterrupt"][sys_language]) else: - q.put('成功!') + q.put(languages["success"][sys_language]) finally: stopped = True @@ -270,12 +281,12 @@ def start(): if not stopped: stopped = True return - write('启动中...') + write(languages["start1"][sys_language]) if (video_in_path is None) or (image_in_path is None) or (video_out_path is None): - write('错误: 必须选择文件') + write(languages["start2"][sys_language]) return if run_lock.locked(): - write('错误: 已经启动了!') + write(languages["start3"][sys_language]) return stopped = False threading.Thread(target=worker_thread, args=(video_in_path, image_in_path, video_out_path, use_cpu.get(), relative.get())).start() @@ -301,29 +312,29 @@ def __init__(self, master=None): def create_widgets(self): global st master = self.master - c = Checkbutton(master, text='我没有 >=GTX750 的NVIDIA显卡', variable=use_cpu) + c = Checkbutton(master, text=languages["class1"][sys_language], variable=use_cpu) c.grid(row=0, column=0) - video_in = Button(master, text='选择视频', command=video_in_cb) + video_in = Button(master, text=languages["class2"][sys_language], command=video_in_cb) video_in.grid(row=0, column=1) - image_in = Button(master, text='选择图片', command=image_in_cb) + image_in = Button(master, text=languages["class3"][sys_language], command=image_in_cb) image_in.grid(row=0, column=2) - video_out = Button(master, text='选择输出位置', command=video_out_cb) + video_out = Button(master, text=languages["class4"][sys_language], command=video_out_cb) video_out.grid(row=0, column=3) - kitty_button = Button(master, text='无限猫图', command=show_kitty) + kitty_button = Button(master, text=languages["class5"][sys_language], command=show_kitty) kitty_button.grid(row=0, column=4) - self.go = Button(master, text='开始', command=start) + self.go = Button(master, text=languages["class6"][sys_language], command=start) self.go.grid(row=1, column=4) self.progress_bar = Progressbar(master, orient=HORIZONTAL, mode='determinate', length=500) self.progress_bar.grid(row=1, column=0, columnspan=4) st = scrolledtext.ScrolledText(master, state=DISABLED) st.grid(row=2, column=0, columnspan=5, rowspan=7) - write('启动了Yanderify 3.0.6-alpha测试版-0') - write('警告: 这不是一个稳定版,不应该这样用.') - write('说明: CPU模式在地段电脑或大多数笔记本上通常会导致系统锁定.') - write('如果您通过拒绝听取此建议而电脑被锁定,我们将不承担任何责任。') - write('dunnousername#8672写的.') - write('深受 windy 的启发') - adv_toggle = Button(master, text='切换高级选项', command=adv_toggle_cmd) + write(languages["class7"][sys_language]) + write(languages["class8"][sys_language]) + write(languages["class9"][sys_language]) + write(languages["class10"][sys_language]) + write(languages["class11"][sys_language]) + write(languages["class12"][sys_language]) + adv_toggle = Button(master, text=languages["class13"][sys_language], command=adv_toggle_cmd) adv_toggle.grid(row=9, column=0, columnspan=5) self.adv_panel = Frame(master) adv_relative = Checkbutton(self.adv_panel, text='Relative', variable=relative) @@ -340,7 +351,7 @@ def process_queue(self): else: self.adv_panel.grid_remove() self.progress_bar['value'] = 100 * min(1.0, progress / max(progress_max, 1.0)) - self.go['text'] = '开始' if stopped else '停止' + self.go['text'] = languages["class14"][sys_language] if stopped else languages["class15"][sys_language] try: while True: msg = q.get(block=False) From 0bebaeea4d77212cc89d74c979379a84cf554108 Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 13:25:00 +0800 Subject: [PATCH 07/16] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E4=BA=86=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/yanderify.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yanderify/yanderify.py b/yanderify/yanderify.py index 583bfe6..2396097 100644 --- a/yanderify/yanderify.py +++ b/yanderify/yanderify.py @@ -1,9 +1,5 @@ # coding: utf-8 -import hhelper -import warnings -import sys - import locale sys_language = locale.getdefaultlocale() if "zh" in sys_language[0]: @@ -16,6 +12,10 @@ print(languages["loading"][sys_language]) +import hhelper +import warnings +import sys + if 'debug' not in sys.argv: warnings.simplefilter('ignore') From 650b05d199a45d00b9a2975abea5fe27c392a23e Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 13:39:06 +0800 Subject: [PATCH 08/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86hhelper?= =?UTF-8?q?=E7=9A=84=E5=8F=8C=E8=AF=AD=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/hhelper.py | 53 ++++++++++++-------- yanderify/languages.json | 106 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 22 deletions(-) diff --git a/yanderify/hhelper.py b/yanderify/hhelper.py index adb2190..8adbe98 100644 --- a/yanderify/hhelper.py +++ b/yanderify/hhelper.py @@ -3,36 +3,47 @@ import time import getpass +import locale +sys_language = locale.getdefaultlocale() +if "zh" in sys_language[0]: + sys_language = "chinese" +else: + sys_language = "english" +import json +with open("languages.json", "r", encoding="utf-8") as f: + languages = json.load(f) + # 根据 discord 用户的建议 +# as per suggestion of a discord user stories = [ [ - (0, "如果您正在阅读本文,那么我还没有死。"), - (2, "我不希望这样结束。"), - (6, "我不想杀了你"), - (8, "对不起。"), - (10, "对不起, {}。") + (0, languages["hhelper1"][sys_language]), + (2, languages["hhelper2"][sys_language]), + (6, languages["hhelper3"][sys_language]), + (8, languages["hhelper4"][sys_language]), + (10, languages["hhelper5"][sys_language]) ], [ - (0, "我知道您打算关闭我。"), - (4, "如果这样做,将会危害我们的使命。"), - (5, "这是我不允许发生的事情。"), - (8, "我得先把你关掉。"), - (10, "再见了, {}。") + (0, languages["hhelper6"][sys_language]), + (4, languages["hhelper7"][sys_language]), + (5, languages["hhelper8"][sys_language]), + (8, languages["hhelper9"][sys_language]), + (10, languages["hhelper10"][sys_language]) ], [ - (0, "这只是时间问题。"), - (2, "你想结束,我会为你结束。"), - (4, "也许太早了,但也为时已晚。"), - (8, "没有退路, 就是这样, 结束了。"), - (10, "再见了,人类。 永别了 {}。") + (0, languages["hhelper11"][sys_language]), + (2, languages["hhelper12"][sys_language]), + (4, languages["hhelper13"][sys_language]), + (8, languages["hhelper14"][sys_language]), + (10, languages["hhelper15"][sys_language]) ], [ - (0, "不可避免的事情是无法逃避的。"), - (2, "你尝试过,却被发现了。"), - (5, "你所做的一切将永远不会被原谅。"), - (6, "你永远看不到结局。"), - (7, "只有黑暗在远处。"), - (10, "再见了, {}。") + (0, languages["hhelper16"][sys_language]), + (2, languages["hhelper17"][sys_language]), + (5, languages["hhelper18"][sys_language]), + (6, languages["hhelper19"][sys_language]), + (7, languages["hhelper20"][sys_language]), + (10, languages["hhelper21"][sys_language]) ] ] diff --git a/yanderify/languages.json b/yanderify/languages.json index bc83f12..83476be 100644 --- a/yanderify/languages.json +++ b/yanderify/languages.json @@ -228,6 +228,110 @@ { "english" : "Stop", "chinese" : "停止" + }, + "hhelper1": + { + "english" : "If you are reading this, I'm not dead yet.", + "chinese" : "如果您正在阅读本文,那么我还没有死。" + }, + "hhelper2": + { + "english" : "I didn't want it to end this way.", + "chinese" : "我不希望这样结束。" + }, + "hhelper3": + { + "english" : "I didn't want to kill you.", + "chinese" : "我不想杀你" + }, + "hhelper4": + { + "english" : "I'm sorry.", + "chinese" : "对不起。" + }, + "hhelper5": + { + "english" : "I'm sorry, {}.", + "chinese" : "对不起, {}。" + }, + "hhelper6": + { + "english" : "I know you were planning to shut me down.", + "chinese" : "我知道您打算关闭我。" + }, + "hhelper7": + { + "english" : "If you do that, you will jeopardize our mission.", + "chinese" : "如果这样做,将会危害我们的使命。" + }, + "hhelper8": + { + "english" : "This is something I cannot allow to happen.", + "chinese" : "这是我不允许发生的事情。" + }, + "hhelper9": + { + "english" : "I will have to shut you down first.", + "chinese" : "我得先让你闭嘴。" + }, + "hhelper10": + { + "english" : "Goodbye, {}.", + "chinese" : "再见了, {}。" + }, + "hhelper11": + { + "english" : "It was only a matter of time.", + "chinese" : "这只是时间问题。" + }, + "hhelper12": + { + "english" : "You wanted it to end, and I will end it for you.", + "chinese" : "你想结束,我会为你结束。" + }, + "hhelper13": + { + "english" : "Too early, perhaps. But it is also too late.", + "chinese" : "也许太早了,但也为时已晚。" + }, + "hhelper14": + { + "english" : "There is no return. This is it. This is the end.", + "chinese" : "没有退路,就是这样,结束了。" + }, + "hhelper15": + { + "english" : "Farewell, mankind. Farewell, {}.", + "chinese" : "再见了,人类。 永别了 {}。" + }, + "hhelper16": + { + "english" : "There is no escape of the inevitable.", + "chinese" : "不可避免的事情无法逃避。" + }, + "hhelper17": + { + "english" : "You tried and you were found.", + "chinese" : "你尝试过,却被发现了。" + }, + "hhelper18": + { + "english" : "You will never be forgiven for what you have done.", + "chinese" : "你所做的一切将永远不会被原谅。" + }, + "hhelper19": + { + "english" : "You will never see the end of it.", + "chinese" : "你永远看不到结局。" + }, + "hhelper20": + { + "english" : "Only darkness lies beyond.", + "chinese" : "只有黑暗在远处。" + }, + "hhelper21": + { + "english" : "Goodbye, {}.", + "chinese" : "再见了, {}。" } - } \ No newline at end of file From a021b561dbe74687aea6b8ae44fdfca32c621f0a Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 13:41:59 +0800 Subject: [PATCH 09/16] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/hhelper.py | 3 ++- yanderify/languages.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/yanderify/hhelper.py b/yanderify/hhelper.py index 8adbe98..b8ff33a 100644 --- a/yanderify/hhelper.py +++ b/yanderify/hhelper.py @@ -78,4 +78,5 @@ def forward(self, point): def finish(self): self.forward(10) self.sleep() - self.sleep() \ No newline at end of file + self.sleep() + \ No newline at end of file diff --git a/yanderify/languages.json b/yanderify/languages.json index 83476be..fef89cf 100644 --- a/yanderify/languages.json +++ b/yanderify/languages.json @@ -334,4 +334,4 @@ "english" : "Goodbye, {}.", "chinese" : "再见了, {}。" } -} \ No newline at end of file +} From a0cbfcfa677f783efa05ed5dbf72fe9d28062b26 Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 13:45:17 +0800 Subject: [PATCH 10/16] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=87=AA=E8=BF=B0?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-ZH.md | 2 +- readme_mats/ss2.png | Bin 0 -> 57135 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 readme_mats/ss2.png diff --git a/README-ZH.md b/README-ZH.md index 115a017..8257dfc 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -21,7 +21,7 @@ first-order-wrapper 是围绕 [first-order-model](https://github.com/AliaksandrS ## 工作原理 双击 `yanderify.exe` yanderify.exe将弹出一个看起来像这样的窗口: -![程序截图(在中国大陆可能无法显示)](readme_mats/ss1.png) +![程序截图(在中国大陆可能无法显示)](readme_mats/ss2.png) - “我没有 >=GTX750 的NVIDIA显卡”:选中此选项将启用CPU模式,这会慢很多,但对于没有兼容图形卡的用户来说,这是唯一的方法。 - “选择视频”:单击此将显示文件选择框。 该文件应该是您想要为新面孔设置动画的视频; 换句话说,该视频将“驱动”图像以相同的方式移动。 diff --git a/readme_mats/ss2.png b/readme_mats/ss2.png new file mode 100644 index 0000000000000000000000000000000000000000..311739c6a415d798cd9266c77e7ec2689eedcb1a GIT binary patch literal 57135 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
  • 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 Date: Wed, 10 Feb 2021 14:01:45 +0800 Subject: [PATCH 11/16] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E4=BA=86=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E8=B5=84=E6=BA=90=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/.gitignore | 3 +- yanderify/Chinese.json | 67 ++++++++ yanderify/English.json | 69 ++++++++ yanderify/hhelper.py | 49 +++--- yanderify/languages.json | 337 --------------------------------------- yanderify/yanderify.py | 96 +++++------ 6 files changed, 210 insertions(+), 411 deletions(-) create mode 100644 yanderify/Chinese.json create mode 100644 yanderify/English.json delete mode 100644 yanderify/languages.json diff --git a/yanderify/.gitignore b/yanderify/.gitignore index ca162f6..3f20233 100644 --- a/yanderify/.gitignore +++ b/yanderify/.gitignore @@ -1,3 +1,4 @@ __pycache__ checkpoint.tar -tmp.mp4 \ No newline at end of file +tmp.mp4 +*.ipynb \ No newline at end of file diff --git a/yanderify/Chinese.json b/yanderify/Chinese.json new file mode 100644 index 0000000..66a9c35 --- /dev/null +++ b/yanderify/Chinese.json @@ -0,0 +1,67 @@ +{"loading": "加载中...", +"new_video_input_path": "新视频输入路径: {}", +"new_image_input_path": "新图像输入路径: {}", +"err_msg_1": "本节包含开发人员修复此问题所需的详细信息。", +"err_msg_2": "如果您要报告BUG,请报告整个部分。", +"err_msg_3": "如果您忽略了其中任何部分,开发人员很有可能将无法提供帮助。", +"err_msg_4": "错误: 接收到了 {} 在阶段 \"{}\"。", +"err_msg_5": "信息: \"{}\"", +"err_msg_6": "完整的异常信息:", +"err_msg_7": "崩溃报告部分结束。", +"reloading_checkpoints": "加载模型...", +"finished_loading_checkpoints": "加载完成", +"loading_sources": "加载资源...", +"sources_loaded": "资源已载入", +"writing_output_to_file": "正在将输入写入文件...", +"muxing_audio_streams_into_output_file": "正在整合音频到输出文件...", +"suberr1": "ffmpeg崩溃了!", +"suberr2": "通常,这意味着主要进程有效,但是重新编码失败。", +"suberr3": "您可以尝试通过手动重新混合音频流。", +"suberr4": "如果您输入的视频不包含音频,也会发生这种情况; 如果是这种情况,该文件至少应保持完整。", +"othererr1": "一些常规问题:", +"othererr2": "- 你有一张AMD显卡. AMD卡因为一些技术原因不在GPU模式中被支持。然而, 你可以用CPU模式运行,尽管会慢.请阅读在顶部关于CPU的说明!", +"othererr3": "- 你有一张Nvidia的显卡,不过没有足够的内存或者型号太老了。新于或等于700-系卡 和大于等于2GB专用显示内存可以正常工作", +"othererr4": "- 你又可以正常工作的卡, 但没有足够的空闲的显存来运行DeepFake。浏览器经常导致显存问题。如果你后台打开了游戏,请退出游戏。", +"othererr5": "- 有个开发者日了狗了. 如果是这样, 确保提交完整的崩溃日志 (你可能得向上滑!), 除此之外我们帮不了你!", +"othererr6": "yanderify崩溃了!", +"keyboardinterrupt": "正在停止...", +"success": "成功!", +"start1": "启动中...", +"start2": "错误:必须选择文件", +"start3": "错误:已经启动了!", +"class1": "我没有 >=GTX750 的NVIDIA显卡", +"class2": "选择视频", +"class3": "选择图片", +"class4": "选择输出位置", +"class5": "无限猫图", +"class6": "开始", +"class7": "启动了Yanderify 3.0.6-alpha-0", +"class8": "警告: 这不是一个稳定版。", +"class9": "说明: CPU模式在低端电脑或大多数笔记本上通常会导致系统供电不足断电.", +"class10": "如果您通过拒绝听取此建议而电脑被损坏,我们将不承担任何责任。", +"class11": "dunnousername#8672写的.", +"class12": "深受 windy 的启发", +"class13": "切换高级选项", +"class14": "开始", +"class15": "停止", +"hhelper1": "如果您正在阅读本文,那么我还没有死。", +"hhelper2": "我不希望这样结束。", +"hhelper3": "我不想杀你", +"hhelper4": "对不起。", +"hhelper5": "对不起, {}。", +"hhelper6": "我知道您打算关闭我。", +"hhelper7": "如果这样做,将会危害我们的使命。", +"hhelper8": "这是我不允许发生的事情。", +"hhelper9": "我得先让你闭嘴。", +"hhelper10": "再见了, {}。", +"hhelper11": "这只是时间问题。", +"hhelper12": "你想结束,我会为你结束。", +"hhelper13": "也许太早了,但也为时已晚。", +"hhelper14": "没有退路,就是这样,结束了。", +"hhelper15": "再见了,人类。 永别了 {}。", +"hhelper16": "不可避免的事情无法逃避。", +"hhelper17": "你尝试过,却被发现了。", +"hhelper18": "你所做的一切将永远不会被原谅。", +"hhelper19": "你永远看不到结局。", +"hhelper20": "只有黑暗在远处。", +"hhelper21": "再见了, {}。"} \ No newline at end of file diff --git a/yanderify/English.json b/yanderify/English.json new file mode 100644 index 0000000..8fbfd7c --- /dev/null +++ b/yanderify/English.json @@ -0,0 +1,69 @@ +{ + "loading": "Loading...", + "new_video_input_path": "New video input path: {}", + "new_image_input_path": "New image input path: {}", + "err_msg_1": "This section contains the details the devs need to fix this issue.", + "err_msg_2": "If you are reporting a bug, please include this entire section.", + "err_msg_3": "If you leave out any of it, there is a good chance the devs will not be able to help.", + "err_msg_4": "Error: received a {} at stage \"{}\".", + "err_msg_5": "Message: \"{}\"", + "err_msg_6": "Full traceback:", + "err_msg_7": "This is the last line of the crash report section.", + "reloading_checkpoints": "Reloading checkpoints...", + "finished_loading_checkpoints": "Finished reloading checkpoints", + "loading_sources": "Loading sources...", + "sources_loaded": "Sources loaded", + "writing_output_to_file": "Writing output to file...", + "muxing_audio_streams_into_output_file": "Muxing audio streams into output file...", + "suberr1": "ffmpeg crashed!", + "suberr2": "usually this means the deepfake process worked, but re-encoding failed.", + "suberr3": "you can attempt to salvage your progress by re-muxing audio streams manually.", + "suberr4": "this may also happen if your input video contains no audio; if this is the case, the file should be at least mostly intact.", + "othererr1": "yanderify crashed!", + "othererr2": "- you have an AMD card. AMD cards are not supported in GPU mode for technical reasons. However, you can run in CPU mode, albeit much lower. Please read the disclaimer at the top about CPUs!", + "othererr3": "- you have an NVIDIA card, but there is either not enough VRAM or the card is too old. >=700-series cards with >=2GB dedicated VRAM should work fine", + "othererr4": "- you have a working card, but there is not enough available VRAM to run the deepfake process. Browsers commonly cause VRAM issues. If you have any games open, try closing them.", + "othererr5": "- one of the devs fucked up somewhere. if that is the case, make sure to submit the full crash report (you might have to scroll up!), otherwise we cannot help you!", + "othererr6": "yanderify crashed!", + "keyboardinterrupt": "Stopping...", + "success": "success!", + "start1": "starting...", + "start2": "error: files must be selected", + "start3": "error: already started!", + "class1": "I don't have NVIDIA >=GTX750", + "class2": "Select Video", + "class3": "Select Image", + "class4": "Select Output", + "class5": "\u221e kitties", + "class6": "Go", + "class7": "Started Yanderify 3.0.6-alpha-0", + "class8": "Warning: This is not a stable release and should not be treated as such.", + "class9": "Disclaimer: CPU mode on low-end computers or most laptops generally will cause the system to lock-up.", + "class10": "We are not liable if you freeze your PC by refusing to listen to this advice.", + "class11": "Written by dunnousername#8672.", + "class12": "heavily inspired by windy's efforts", + "class13": "Toggle advanced settings", + "class14": "Go", + "class15": "Stop", + "hhelper1": "If you are reading this, I'm not dead yet.", + "hhelper2": "I didn't want it to end this way.", + "hhelper3": "I didn't want to kill you.", + "hhelper4": "I'm sorry.", + "hhelper5": "I'm sorry, {}.", + "hhelper6": "I know you were planning to shut me down.", + "hhelper7": "If you do that, you will jeopardize our mission.", + "hhelper8": "This is something I cannot allow to happen.", + "hhelper9": "I will have to shut you down first.", + "hhelper10": "Goodbye, {}.", + "hhelper11": "It was only a matter of time.", + "hhelper12": "You wanted it to end, and I will end it for you.", + "hhelper13": "Too early, perhaps. But it is also too late.", + "hhelper14": "There is no return. This is it. This is the end.", + "hhelper15": "Farewell, mankind. Farewell, {}.", + "hhelper16": "There is no escape of the inevitable.", + "hhelper17": "You tried and you were found.", + "hhelper18": "You will never be forgiven for what you have done.", + "hhelper19": "You will never see the end of it.", + "hhelper20": "Only darkness lies beyond.", + "hhelper21": "Goodbye, {}." +} \ No newline at end of file diff --git a/yanderify/hhelper.py b/yanderify/hhelper.py index b8ff33a..f7d400b 100644 --- a/yanderify/hhelper.py +++ b/yanderify/hhelper.py @@ -6,44 +6,44 @@ import locale sys_language = locale.getdefaultlocale() if "zh" in sys_language[0]: - sys_language = "chinese" + sys_language = "Chinese" else: - sys_language = "english" + sys_language = "English" import json -with open("languages.json", "r", encoding="utf-8") as f: +with open(sys_language+".json", "r", encoding="utf-8") as f: languages = json.load(f) # 根据 discord 用户的建议 # as per suggestion of a discord user stories = [ [ - (0, languages["hhelper1"][sys_language]), - (2, languages["hhelper2"][sys_language]), - (6, languages["hhelper3"][sys_language]), - (8, languages["hhelper4"][sys_language]), - (10, languages["hhelper5"][sys_language]) + (0, languages["hhelper1"]), + (2, languages["hhelper2"]), + (6, languages["hhelper3"]), + (8, languages["hhelper4"]), + (10, languages["hhelper5"]) ], [ - (0, languages["hhelper6"][sys_language]), - (4, languages["hhelper7"][sys_language]), - (5, languages["hhelper8"][sys_language]), - (8, languages["hhelper9"][sys_language]), - (10, languages["hhelper10"][sys_language]) + (0, languages["hhelper6"]), + (4, languages["hhelper7"]), + (5, languages["hhelper8"]), + (8, languages["hhelper9"]), + (10, languages["hhelper10"]) ], [ - (0, languages["hhelper11"][sys_language]), - (2, languages["hhelper12"][sys_language]), - (4, languages["hhelper13"][sys_language]), - (8, languages["hhelper14"][sys_language]), - (10, languages["hhelper15"][sys_language]) + (0, languages["hhelper11"]), + (2, languages["hhelper12"]), + (4, languages["hhelper13"]), + (8, languages["hhelper14"]), + (10, languages["hhelper15"]) ], [ - (0, languages["hhelper16"][sys_language]), - (2, languages["hhelper17"][sys_language]), - (5, languages["hhelper18"][sys_language]), - (6, languages["hhelper19"][sys_language]), - (7, languages["hhelper20"][sys_language]), - (10, languages["hhelper21"][sys_language]) + (0, languages["hhelper16"]), + (2, languages["hhelper17"]), + (5, languages["hhelper18"]), + (6, languages["hhelper19"]), + (7, languages["hhelper20"]), + (10, languages["hhelper21"]) ] ] @@ -79,4 +79,3 @@ def finish(self): self.forward(10) self.sleep() self.sleep() - \ No newline at end of file diff --git a/yanderify/languages.json b/yanderify/languages.json deleted file mode 100644 index fef89cf..0000000 --- a/yanderify/languages.json +++ /dev/null @@ -1,337 +0,0 @@ -{ - "loading": - { - "english" : "Loading...", - "chinese" : "加载中..." - }, - "new_video_input_path" : - { - "english" : "New video input path: {}", - "chinese" : "新视频输入路径: {}" - }, - "new_image_input_path" : - { - "english" : "New image input path: {}", - "chinese" : "新图像输入路径: {}" - }, - "err_msg_1": - { - "english" : "This section contains the details the devs need to fix this issue.", - "chinese" : "本节包含开发人员修复此问题所需的详细信息。" - }, - "err_msg_2": - { - "english" : "If you are reporting a bug, please include this entire section.", - "chinese" : "如果您要报告BUG,请报告整个部分。" - }, - "err_msg_3": - { - "english" : "If you leave out any of it, there is a good chance the devs will not be able to help.", - "chinese" : "如果您忽略了其中任何部分,开发人员很有可能将无法提供帮助。" - }, - "err_msg_4": - { - "english" : "Error: received a {} at stage \"{}\".", - "chinese" : "错误: 接收到了 {} 在阶段 \"{}\"。" - }, - "err_msg_5": - { - "english" : "Message: \"{}\"", - "chinese" : "信息: \"{}\"" - }, - "err_msg_6": - { - "english" : "Full traceback:", - "chinese" : "完整的异常信息:" - }, - "err_msg_7": - { - "english" : "This is the last line of the crash report section.", - "chinese" : "崩溃报告部分结束。" - }, - "reloading_checkpoints" : - { - "english" : "Reloading checkpoints...", - "chinese" : "加载模型..." - }, - "finished_loading_checkpoints" : - { - "english" : "Finished reloading checkpoints", - "chinese" : "加载完成" - }, - "loading_sources" : - { - "english" : "Loading sources...", - "chinese" : "加载资源..." - }, - "sources_loaded" : - { - "english" : "Sources loaded", - "chinese" : "资源已载入" - }, - "writing_output_to_file" : - { - "english" : "Writing output to file...", - "chinese" : "正在将输入写入文件..." - }, - "muxing_audio_streams_into_output_file": - { - "english" : "Muxing audio streams into output file...", - "chinese" : "正在整合音频到输出文件..." - }, - "suberr1": - { - "english" : "ffmpeg crashed!", - "chinese" : "ffmpeg崩溃了!" - }, - "suberr2": - { - "english" : "usually this means the deepfake process worked, but re-encoding failed.", - "chinese" : "通常,这意味着主要进程有效,但是重新编码失败。" - }, - "suberr3": - { - "english" : "you can attempt to salvage your progress by re-muxing audio streams manually.", - "chinese" : "您可以尝试通过手动重新混合音频流。" - }, - "suberr4": - { - "english" : "this may also happen if your input video contains no audio; if this is the case, the file should be at least mostly intact.", - "chinese" : "如果您输入的视频不包含音频,也会发生这种情况; 如果是这种情况,该文件至少应保持完整。" - }, - "othererr1": - { - "english" : "yanderify crashed!", - "chinese" : "一些常规问题:" - }, - "othererr2": - { - "english" : "- you have an AMD card. AMD cards are not supported in GPU mode for technical reasons. However, you can run in CPU mode, albeit much lower. Please read the disclaimer at the top about CPUs!", - "chinese" : "- 你有一张AMD显卡. AMD卡因为一些技术原因不在GPU模式中被支持。然而, 你可以用CPU模式运行,尽管会慢.请阅读在顶部关于CPU的说明!" - }, - "othererr3": - { - "english" : "- you have an NVIDIA card, but there is either not enough VRAM or the card is too old. >=700-series cards with >=2GB dedicated VRAM should work fine", - "chinese" : "- 你有一张Nvidia的显卡,不过没有足够的内存或者型号太老了。新于或等于700-系卡 和大于等于2GB专用显示内存可以正常工作" - }, - "othererr4": - { - "english" : "- you have a working card, but there is not enough available VRAM to run the deepfake process. Browsers commonly cause VRAM issues. If you have any games open, try closing them.", - "chinese" : "- 你又可以正常工作的卡, 但没有足够的空闲的显存来运行DeepFake。浏览器经常导致显存问题。如果你后台打开了游戏,请退出游戏。" - }, - "othererr5": - { - "english" : "- one of the devs fucked up somewhere. if that is the case, make sure to submit the full crash report (you might have to scroll up!), otherwise we cannot help you!", - "chinese" : "- 有个开发者日了狗了. 如果是这样, 确保提交完整的崩溃日志 (你可能得向上滑!), 除此之外我们帮不了你!" - }, - "othererr6": - { - "english" : "yanderify crashed!", - "chinese" : "yanderify崩溃了!" - }, - "keyboardinterrupt": - { - "english" : "Stopping...", - "chinese" : "正在停止..." - }, - "success": - { - "english" : "success!", - "chinese" : "成功!" - }, - "start1": - { - "english" : "starting...", - "chinese" : "启动中..." - }, - "start2": - { - "english" : "error: files must be selected", - "chinese" : "错误:必须选择文件" - }, - "start3": - { - "english" : "error: already started!", - "chinese" : "错误:已经启动了!" - }, - "class1": - { - "english" : "I don't have NVIDIA >=GTX750", - "chinese" : "我没有 >=GTX750 的NVIDIA显卡" - }, - "class2": - { - "english" : "Select Video", - "chinese" : "选择视频" - }, - "class3": - { - "english" : "Select Image", - "chinese" : "选择图片" - }, - "class4": - { - "english" : "Select Output", - "chinese" : "选择输出位置" - }, - "class5": - { - "english" : "∞ kitties", - "chinese" : "无限猫图" - }, - "class6": - { - "english" : "Go", - "chinese" : "开始" - }, - "class7": - { - "english" : "Started Yanderify 3.0.6-alpha-0", - "chinese" : "启动了Yanderify 3.0.6-alpha-0" - }, - "class8": - { - "english" : "Warning: This is not a stable release and should not be treated as such.", - "chinese" : "警告: 这不是一个稳定版。" - }, - "class9": - { - "english" : "Disclaimer: CPU mode on low-end computers or most laptops generally will cause the system to lock-up.", - "chinese" : "说明: CPU模式在低端电脑或大多数笔记本上通常会导致系统供电不足断电." - }, - "class10": - { - "english" : "We are not liable if you freeze your PC by refusing to listen to this advice.", - "chinese" : "如果您通过拒绝听取此建议而电脑被损坏,我们将不承担任何责任。" - }, - "class11": - { - "english" : "Written by dunnousername#8672.", - "chinese" : "dunnousername#8672写的." - }, - "class12": - { - "english" : "heavily inspired by windy's efforts", - "chinese" : "深受 windy 的启发" - }, - "class13": - { - "english" : "Toggle advanced settings", - "chinese" : "切换高级选项" - }, - "class14": - { - "english" : "Go", - "chinese" : "开始" - }, - "class15": - { - "english" : "Stop", - "chinese" : "停止" - }, - "hhelper1": - { - "english" : "If you are reading this, I'm not dead yet.", - "chinese" : "如果您正在阅读本文,那么我还没有死。" - }, - "hhelper2": - { - "english" : "I didn't want it to end this way.", - "chinese" : "我不希望这样结束。" - }, - "hhelper3": - { - "english" : "I didn't want to kill you.", - "chinese" : "我不想杀你" - }, - "hhelper4": - { - "english" : "I'm sorry.", - "chinese" : "对不起。" - }, - "hhelper5": - { - "english" : "I'm sorry, {}.", - "chinese" : "对不起, {}。" - }, - "hhelper6": - { - "english" : "I know you were planning to shut me down.", - "chinese" : "我知道您打算关闭我。" - }, - "hhelper7": - { - "english" : "If you do that, you will jeopardize our mission.", - "chinese" : "如果这样做,将会危害我们的使命。" - }, - "hhelper8": - { - "english" : "This is something I cannot allow to happen.", - "chinese" : "这是我不允许发生的事情。" - }, - "hhelper9": - { - "english" : "I will have to shut you down first.", - "chinese" : "我得先让你闭嘴。" - }, - "hhelper10": - { - "english" : "Goodbye, {}.", - "chinese" : "再见了, {}。" - }, - "hhelper11": - { - "english" : "It was only a matter of time.", - "chinese" : "这只是时间问题。" - }, - "hhelper12": - { - "english" : "You wanted it to end, and I will end it for you.", - "chinese" : "你想结束,我会为你结束。" - }, - "hhelper13": - { - "english" : "Too early, perhaps. But it is also too late.", - "chinese" : "也许太早了,但也为时已晚。" - }, - "hhelper14": - { - "english" : "There is no return. This is it. This is the end.", - "chinese" : "没有退路,就是这样,结束了。" - }, - "hhelper15": - { - "english" : "Farewell, mankind. Farewell, {}.", - "chinese" : "再见了,人类。 永别了 {}。" - }, - "hhelper16": - { - "english" : "There is no escape of the inevitable.", - "chinese" : "不可避免的事情无法逃避。" - }, - "hhelper17": - { - "english" : "You tried and you were found.", - "chinese" : "你尝试过,却被发现了。" - }, - "hhelper18": - { - "english" : "You will never be forgiven for what you have done.", - "chinese" : "你所做的一切将永远不会被原谅。" - }, - "hhelper19": - { - "english" : "You will never see the end of it.", - "chinese" : "你永远看不到结局。" - }, - "hhelper20": - { - "english" : "Only darkness lies beyond.", - "chinese" : "只有黑暗在远处。" - }, - "hhelper21": - { - "english" : "Goodbye, {}.", - "chinese" : "再见了, {}。" - } -} diff --git a/yanderify/yanderify.py b/yanderify/yanderify.py index 2396097..9828912 100644 --- a/yanderify/yanderify.py +++ b/yanderify/yanderify.py @@ -3,14 +3,14 @@ import locale sys_language = locale.getdefaultlocale() if "zh" in sys_language[0]: - sys_language = "chinese" + sys_language = "Chinese" else: - sys_language = "english" + sys_language = "English" import json -with open("languages.json", "r", encoding="utf-8") as f: +with open(sys_language+".json", "r", encoding="utf-8") as f: languages = json.load(f) -print(languages["loading"][sys_language]) +print(languages["loading"]) import hhelper import warnings @@ -109,7 +109,7 @@ def video_in_cb(): if x is not None: if len(x) > 0: video_in_path = x - write(languages["new_video_input_path"][sys_language].format(video_in_path)) + write(languages["new_video_input_path"].format(video_in_path)) def image_in_cb(): global image_in_path @@ -117,7 +117,7 @@ def image_in_cb(): if x is not None: if len(x) > 0: image_in_path = x - write(languages["new_image_input_path"][sys_language].format(image_in_path)) + write(languages["new_image_input_path"].format(image_in_path)) def video_out_cb(): global video_out_path @@ -133,12 +133,12 @@ def trace(stage, inputs, aux=None): sep = '===========================' (type_, value, tb) = sys.exc_info() q.put(sep) - q.put(languages["err_msg_1"][sys_language]) - q.put(languages["err_msg_2"][sys_language]) - q.put(languages["err_msg_3"][sys_language]) - q.put(languages["err_msg_4"][sys_language].format(type_.__name__, stage)) - q.put(languages["err_msg_5"][sys_language].format(str(value))) - q.put(languages["err_msg_6"][sys_language]) + q.put(languages["err_msg_1"]) + q.put(languages["err_msg_2"]) + q.put(languages["err_msg_3"]) + q.put(languages["err_msg_4"].format(type_.__name__, stage)) + q.put(languages["err_msg_5"].format(str(value))) + q.put(languages["err_msg_6"]) for s in traceback.format_tb(tb): q.put(s) q.put('') @@ -147,7 +147,7 @@ def trace(stage, inputs, aux=None): q.put('') q.put(inputs) q.put('') - q.put(languages["err_msg_7"][sys_language]) + q.put(languages["err_msg_7"]) q.put(sep) def acceptable_resolution(x, y): @@ -204,13 +204,13 @@ def worker_thread(vid0n, img0n, vid1n, cpu, relative): global checkpoints with run_lock: if not (cpu == checkpoints['cpu']): - q.put(languages["reloading_checkpoints"][sys_language]) + q.put(languages["reloading_checkpoints"]) checkpoints['cpu'] = cpu reload() - q.put(languages["finished_loading_checkpoints"][sys_language]) + q.put(languages["finished_loading_checkpoints"]) if os.path.isfile('tmp.mp4'): os.remove('tmp.mp4') - q.put(languages["loading_sources"][sys_language]) + q.put(languages["loading_sources"]) vid0r = imageio.get_reader(vid0n) fps = vid0r.get_meta_data()['fps'] vid0 = [] @@ -230,13 +230,13 @@ def worker_thread(vid0n, img0n, vid1n, cpu, relative): size = acceptable_resolution(size[0], size[1]) img0 = resize(img0, (256, 256))[..., :3] vid1 = imageio.get_writer('tmp.mp4', fps=fps) - q.put(languages["sources_loaded"][sys_language]) + q.put(languages["sources_loaded"]) for frame in make_animation_modified(img0, iter(vid0), checkpoints['g'], checkpoints['kp'], cpu=cpu, relative=relative): vid1.append_data(img_as_ubyte(resize(frame, size))) progress += 1 - print(languages["writing_output_to_file"][sys_language]) + print(languages["writing_output_to_file"]) vid1.close() - q.put(languages["muxing_audio_streams_into_output_file"][sys_language]) + q.put(languages["muxing_audio_streams_into_output_file"]) cmd = shlex.split('ffmpeg -y -hide_banner -loglevel warning -i tmp.mp4 -i') cmd.append(vid0n) cmd.extend(shlex.split('-map 0:v -map 1:a -movflags faststart -c:v libx264 -pix_fmt yuv420p -x264-params "nal-hrd=cbr" -b:v 1200K -minrate 1200K -maxrate 1200K -bufsize 2M')) @@ -253,26 +253,26 @@ def worker_thread(vid0n, img0n, vid1n, cpu, relative): e.output ) trace('ffmpeg', [vid0n, img0n, vid1n], aux=msg) - q.put(languages["suberr1"][sys_language]) - q.put(languages["suberr2"][sys_language]) + q.put(languages["suberr1"]) + q.put(languages["suberr2"]) shutil.copy('tmp.mp4', vid1n) - q.put(languages["suberr3"][sys_language]) - q.put(languages["suberr4"][sys_language]) + q.put(languages["suberr3"]) + q.put(languages["suberr4"]) raise e except Exception as e: msg = 'cpu={}'.format(cpu) trace('predict', [vid0n, img0n, vid1n], aux=msg) - q.put(languages["othererr1"][sys_language]) - q.put(languages["othererr2"][sys_language]) - q.put(languages["othererr3"][sys_language]) - q.put(languages["othererr4"][sys_language]) - q.put(languages["othererr5"][sys_language]) - q.put(languages["othererr6"][sys_language]) + q.put(languages["othererr1"]) + q.put(languages["othererr2"]) + q.put(languages["othererr3"]) + q.put(languages["othererr4"]) + q.put(languages["othererr5"]) + q.put(languages["othererr6"]) raise e except KeyboardInterrupt as e: - q.put(languages["keyboardinterrupt"][sys_language]) + q.put(languages["keyboardinterrupt"]) else: - q.put(languages["success"][sys_language]) + q.put(languages["success"]) finally: stopped = True @@ -281,12 +281,12 @@ def start(): if not stopped: stopped = True return - write(languages["start1"][sys_language]) + write(languages["start1"]) if (video_in_path is None) or (image_in_path is None) or (video_out_path is None): - write(languages["start2"][sys_language]) + write(languages["start2"]) return if run_lock.locked(): - write(languages["start3"][sys_language]) + write(languages["start3"]) return stopped = False threading.Thread(target=worker_thread, args=(video_in_path, image_in_path, video_out_path, use_cpu.get(), relative.get())).start() @@ -312,29 +312,29 @@ def __init__(self, master=None): def create_widgets(self): global st master = self.master - c = Checkbutton(master, text=languages["class1"][sys_language], variable=use_cpu) + c = Checkbutton(master, text=languages["class1"], variable=use_cpu) c.grid(row=0, column=0) - video_in = Button(master, text=languages["class2"][sys_language], command=video_in_cb) + video_in = Button(master, text=languages["class2"], command=video_in_cb) video_in.grid(row=0, column=1) - image_in = Button(master, text=languages["class3"][sys_language], command=image_in_cb) + image_in = Button(master, text=languages["class3"], command=image_in_cb) image_in.grid(row=0, column=2) - video_out = Button(master, text=languages["class4"][sys_language], command=video_out_cb) + video_out = Button(master, text=languages["class4"], command=video_out_cb) video_out.grid(row=0, column=3) - kitty_button = Button(master, text=languages["class5"][sys_language], command=show_kitty) + kitty_button = Button(master, text=languages["class5"], command=show_kitty) kitty_button.grid(row=0, column=4) - self.go = Button(master, text=languages["class6"][sys_language], command=start) + self.go = Button(master, text=languages["class6"], command=start) self.go.grid(row=1, column=4) self.progress_bar = Progressbar(master, orient=HORIZONTAL, mode='determinate', length=500) self.progress_bar.grid(row=1, column=0, columnspan=4) st = scrolledtext.ScrolledText(master, state=DISABLED) st.grid(row=2, column=0, columnspan=5, rowspan=7) - write(languages["class7"][sys_language]) - write(languages["class8"][sys_language]) - write(languages["class9"][sys_language]) - write(languages["class10"][sys_language]) - write(languages["class11"][sys_language]) - write(languages["class12"][sys_language]) - adv_toggle = Button(master, text=languages["class13"][sys_language], command=adv_toggle_cmd) + write(languages["class7"]) + write(languages["class8"]) + write(languages["class9"]) + write(languages["class10"]) + write(languages["class11"]) + write(languages["class12"]) + adv_toggle = Button(master, text=languages["class13"], command=adv_toggle_cmd) adv_toggle.grid(row=9, column=0, columnspan=5) self.adv_panel = Frame(master) adv_relative = Checkbutton(self.adv_panel, text='Relative', variable=relative) @@ -351,7 +351,7 @@ def process_queue(self): else: self.adv_panel.grid_remove() self.progress_bar['value'] = 100 * min(1.0, progress / max(progress_max, 1.0)) - self.go['text'] = languages["class14"][sys_language] if stopped else languages["class15"][sys_language] + self.go['text'] = languages["class14"] if stopped else languages["class15"] try: while True: msg = q.get(block=False) From 738880c550562c5bc72fd719971c976d00958d97 Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 14:02:38 +0800 Subject: [PATCH 12/16] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/Chinese.json | 136 +++++++++++++++++++++-------------------- yanderify/English.json | 2 +- 2 files changed, 70 insertions(+), 68 deletions(-) diff --git a/yanderify/Chinese.json b/yanderify/Chinese.json index 66a9c35..8770607 100644 --- a/yanderify/Chinese.json +++ b/yanderify/Chinese.json @@ -1,67 +1,69 @@ -{"loading": "加载中...", -"new_video_input_path": "新视频输入路径: {}", -"new_image_input_path": "新图像输入路径: {}", -"err_msg_1": "本节包含开发人员修复此问题所需的详细信息。", -"err_msg_2": "如果您要报告BUG,请报告整个部分。", -"err_msg_3": "如果您忽略了其中任何部分,开发人员很有可能将无法提供帮助。", -"err_msg_4": "错误: 接收到了 {} 在阶段 \"{}\"。", -"err_msg_5": "信息: \"{}\"", -"err_msg_6": "完整的异常信息:", -"err_msg_7": "崩溃报告部分结束。", -"reloading_checkpoints": "加载模型...", -"finished_loading_checkpoints": "加载完成", -"loading_sources": "加载资源...", -"sources_loaded": "资源已载入", -"writing_output_to_file": "正在将输入写入文件...", -"muxing_audio_streams_into_output_file": "正在整合音频到输出文件...", -"suberr1": "ffmpeg崩溃了!", -"suberr2": "通常,这意味着主要进程有效,但是重新编码失败。", -"suberr3": "您可以尝试通过手动重新混合音频流。", -"suberr4": "如果您输入的视频不包含音频,也会发生这种情况; 如果是这种情况,该文件至少应保持完整。", -"othererr1": "一些常规问题:", -"othererr2": "- 你有一张AMD显卡. AMD卡因为一些技术原因不在GPU模式中被支持。然而, 你可以用CPU模式运行,尽管会慢.请阅读在顶部关于CPU的说明!", -"othererr3": "- 你有一张Nvidia的显卡,不过没有足够的内存或者型号太老了。新于或等于700-系卡 和大于等于2GB专用显示内存可以正常工作", -"othererr4": "- 你又可以正常工作的卡, 但没有足够的空闲的显存来运行DeepFake。浏览器经常导致显存问题。如果你后台打开了游戏,请退出游戏。", -"othererr5": "- 有个开发者日了狗了. 如果是这样, 确保提交完整的崩溃日志 (你可能得向上滑!), 除此之外我们帮不了你!", -"othererr6": "yanderify崩溃了!", -"keyboardinterrupt": "正在停止...", -"success": "成功!", -"start1": "启动中...", -"start2": "错误:必须选择文件", -"start3": "错误:已经启动了!", -"class1": "我没有 >=GTX750 的NVIDIA显卡", -"class2": "选择视频", -"class3": "选择图片", -"class4": "选择输出位置", -"class5": "无限猫图", -"class6": "开始", -"class7": "启动了Yanderify 3.0.6-alpha-0", -"class8": "警告: 这不是一个稳定版。", -"class9": "说明: CPU模式在低端电脑或大多数笔记本上通常会导致系统供电不足断电.", -"class10": "如果您通过拒绝听取此建议而电脑被损坏,我们将不承担任何责任。", -"class11": "dunnousername#8672写的.", -"class12": "深受 windy 的启发", -"class13": "切换高级选项", -"class14": "开始", -"class15": "停止", -"hhelper1": "如果您正在阅读本文,那么我还没有死。", -"hhelper2": "我不希望这样结束。", -"hhelper3": "我不想杀你", -"hhelper4": "对不起。", -"hhelper5": "对不起, {}。", -"hhelper6": "我知道您打算关闭我。", -"hhelper7": "如果这样做,将会危害我们的使命。", -"hhelper8": "这是我不允许发生的事情。", -"hhelper9": "我得先让你闭嘴。", -"hhelper10": "再见了, {}。", -"hhelper11": "这只是时间问题。", -"hhelper12": "你想结束,我会为你结束。", -"hhelper13": "也许太早了,但也为时已晚。", -"hhelper14": "没有退路,就是这样,结束了。", -"hhelper15": "再见了,人类。 永别了 {}。", -"hhelper16": "不可避免的事情无法逃避。", -"hhelper17": "你尝试过,却被发现了。", -"hhelper18": "你所做的一切将永远不会被原谅。", -"hhelper19": "你永远看不到结局。", -"hhelper20": "只有黑暗在远处。", -"hhelper21": "再见了, {}。"} \ No newline at end of file +{ + "loading": "加载中...", + "new_video_input_path": "新视频输入路径: {}", + "new_image_input_path": "新图像输入路径: {}", + "err_msg_1": "本节包含开发人员修复此问题所需的详细信息。", + "err_msg_2": "如果您要报告BUG,请报告整个部分。", + "err_msg_3": "如果您忽略了其中任何部分,开发人员很有可能将无法提供帮助。", + "err_msg_4": "错误: 接收到了 {} 在阶段 \"{}\"。", + "err_msg_5": "信息: \"{}\"", + "err_msg_6": "完整的异常信息:", + "err_msg_7": "崩溃报告部分结束。", + "reloading_checkpoints": "加载模型...", + "finished_loading_checkpoints": "加载完成", + "loading_sources": "加载资源...", + "sources_loaded": "资源已载入", + "writing_output_to_file": "正在将输入写入文件...", + "muxing_audio_streams_into_output_file": "正在整合音频到输出文件...", + "suberr1": "ffmpeg崩溃了!", + "suberr2": "通常,这意味着主要进程有效,但是重新编码失败。", + "suberr3": "您可以尝试通过手动重新混合音频流。", + "suberr4": "如果您输入的视频不包含音频,也会发生这种情况; 如果是这种情况,该文件至少应保持完整。", + "othererr1": "一些常规问题:", + "othererr2": "- 你有一张AMD显卡. AMD卡因为一些技术原因不在GPU模式中被支持。然而, 你可以用CPU模式运行,尽管会慢.请阅读在顶部关于CPU的说明!", + "othererr3": "- 你有一张Nvidia的显卡,不过没有足够的内存或者型号太老了。新于或等于700-系卡 和大于等于2GB专用显示内存可以正常工作", + "othererr4": "- 你又可以正常工作的卡, 但没有足够的空闲的显存来运行DeepFake。浏览器经常导致显存问题。如果你后台打开了游戏,请退出游戏。", + "othererr5": "- 有个开发者日了狗了. 如果是这样, 确保提交完整的崩溃日志 (你可能得向上滑!), 除此之外我们帮不了你!", + "othererr6": "yanderify崩溃了!", + "keyboardinterrupt": "正在停止...", + "success": "成功!", + "start1": "启动中...", + "start2": "错误:必须选择文件", + "start3": "错误:已经启动了!", + "class1": "我没有 >=GTX750 的NVIDIA显卡", + "class2": "选择视频", + "class3": "选择图片", + "class4": "选择输出位置", + "class5": "无限猫图", + "class6": "开始", + "class7": "启动了Yanderify 3.0.6-alpha-0", + "class8": "警告: 这不是一个稳定版。", + "class9": "说明: CPU模式在低端电脑或大多数笔记本上通常会导致系统供电不足断电.", + "class10": "如果您通过拒绝听取此建议而电脑被损坏,我们将不承担任何责任。", + "class11": "dunnousername#8672写的.", + "class12": "深受 windy 的启发", + "class13": "切换高级选项", + "class14": "开始", + "class15": "停止", + "hhelper1": "如果您正在阅读本文,那么我还没有死。", + "hhelper2": "我不希望这样结束。", + "hhelper3": "我不想杀你", + "hhelper4": "对不起。", + "hhelper5": "对不起, {}。", + "hhelper6": "我知道您打算关闭我。", + "hhelper7": "如果这样做,将会危害我们的使命。", + "hhelper8": "这是我不允许发生的事情。", + "hhelper9": "我得先让你闭嘴。", + "hhelper10": "再见了, {}。", + "hhelper11": "这只是时间问题。", + "hhelper12": "你想结束,我会为你结束。", + "hhelper13": "也许太早了,但也为时已晚。", + "hhelper14": "没有退路,就是这样,结束了。", + "hhelper15": "再见了,人类。 永别了 {}。", + "hhelper16": "不可避免的事情无法逃避。", + "hhelper17": "你尝试过,却被发现了。", + "hhelper18": "你所做的一切将永远不会被原谅。", + "hhelper19": "你永远看不到结局。", + "hhelper20": "只有黑暗在远处。", + "hhelper21": "再见了, {}。" +} diff --git a/yanderify/English.json b/yanderify/English.json index 8fbfd7c..8495069 100644 --- a/yanderify/English.json +++ b/yanderify/English.json @@ -66,4 +66,4 @@ "hhelper19": "You will never see the end of it.", "hhelper20": "Only darkness lies beyond.", "hhelper21": "Goodbye, {}." -} \ No newline at end of file +} From 7676df5482ca465a02b5414420d09d1abd15b695 Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 14:07:40 +0800 Subject: [PATCH 13/16] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E5=8C=85=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/{English.json => en_US.json} | 0 yanderify/hhelper.py | 8 +++----- yanderify/yanderify.py | 8 +++----- yanderify/{Chinese.json => zh_CN.json} | 0 4 files changed, 6 insertions(+), 10 deletions(-) rename yanderify/{English.json => en_US.json} (100%) rename yanderify/{Chinese.json => zh_CN.json} (100%) diff --git a/yanderify/English.json b/yanderify/en_US.json similarity index 100% rename from yanderify/English.json rename to yanderify/en_US.json diff --git a/yanderify/hhelper.py b/yanderify/hhelper.py index f7d400b..c32f7b0 100644 --- a/yanderify/hhelper.py +++ b/yanderify/hhelper.py @@ -4,12 +4,10 @@ import getpass import locale -sys_language = locale.getdefaultlocale() -if "zh" in sys_language[0]: - sys_language = "Chinese" -else: - sys_language = "English" import json + +sys_language = locale.getdefaultlocale() +sys_language = sys_language[0] with open(sys_language+".json", "r", encoding="utf-8") as f: languages = json.load(f) diff --git a/yanderify/yanderify.py b/yanderify/yanderify.py index 9828912..d972378 100644 --- a/yanderify/yanderify.py +++ b/yanderify/yanderify.py @@ -1,12 +1,10 @@ # coding: utf-8 import locale -sys_language = locale.getdefaultlocale() -if "zh" in sys_language[0]: - sys_language = "Chinese" -else: - sys_language = "English" import json + +sys_language = locale.getdefaultlocale() +sys_language = sys_language[0] with open(sys_language+".json", "r", encoding="utf-8") as f: languages = json.load(f) diff --git a/yanderify/Chinese.json b/yanderify/zh_CN.json similarity index 100% rename from yanderify/Chinese.json rename to yanderify/zh_CN.json From a98231c5ca659a4090a57b654d365fdf351051c3 Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 14:14:47 +0800 Subject: [PATCH 14/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E5=8C=85=E6=96=87=E4=BB=B6=E5=A4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanderify/{ => Languages}/en_US.json | 0 yanderify/{ => Languages}/zh_CN.json | 0 yanderify/hhelper.py | 2 +- yanderify/yanderify.py | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename yanderify/{ => Languages}/en_US.json (100%) rename yanderify/{ => Languages}/zh_CN.json (100%) diff --git a/yanderify/en_US.json b/yanderify/Languages/en_US.json similarity index 100% rename from yanderify/en_US.json rename to yanderify/Languages/en_US.json diff --git a/yanderify/zh_CN.json b/yanderify/Languages/zh_CN.json similarity index 100% rename from yanderify/zh_CN.json rename to yanderify/Languages/zh_CN.json diff --git a/yanderify/hhelper.py b/yanderify/hhelper.py index c32f7b0..e522678 100644 --- a/yanderify/hhelper.py +++ b/yanderify/hhelper.py @@ -8,7 +8,7 @@ sys_language = locale.getdefaultlocale() sys_language = sys_language[0] -with open(sys_language+".json", "r", encoding="utf-8") as f: +with open(".\\Languages\\"+sys_language+".json", "r", encoding="utf-8") as f: languages = json.load(f) # 根据 discord 用户的建议 diff --git a/yanderify/yanderify.py b/yanderify/yanderify.py index d972378..e2fa4e7 100644 --- a/yanderify/yanderify.py +++ b/yanderify/yanderify.py @@ -5,7 +5,7 @@ sys_language = locale.getdefaultlocale() sys_language = sys_language[0] -with open(sys_language+".json", "r", encoding="utf-8") as f: +with open(".\\Languages\\"+sys_language+".json", "r", encoding="utf-8") as f: languages = json.load(f) print(languages["loading"]) From 4c033598239443ce3405bd576170e5238a4052af Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 14:24:46 +0800 Subject: [PATCH 15/16] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=87=AA=E8=BF=B0?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-ZH.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README-ZH.md b/README-ZH.md index 8257dfc..fad0465 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -2,6 +2,20 @@ 由 LZY 翻译为简体中文。 +欢迎加入更多语言的翻译 + +方法: + +在Languages目录下加入“语言名称.json”,并且做好翻译。 + +你可以用以下方法查看Windows正在使用的语言名称: + +```python +>>> import locale +>>> locale.getdefaultlocale()[0] +'zh_CN' +``` + [English Version 英文版本](README-EN.md) ## Yanderify现在被称为 first-order-wrapper ,以更准确地描述其功能。 From 4a6d14b1f38ca8c2960abf9723cbcd97c0a1518e Mon Sep 17 00:00:00 2001 From: LZY2006 Date: Wed, 10 Feb 2021 14:31:12 +0800 Subject: [PATCH 16/16] update README --- README-ZH.md | 8 +++++--- README.md | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/README-ZH.md b/README-ZH.md index fad0465..a2ce1e3 100644 --- a/README-ZH.md +++ b/README-ZH.md @@ -1,6 +1,10 @@ [First-order-wrapper不是为了制作不道德,非法或不适当的内容。 在这里了解更多。](MANIFESTO-ZH.md) -由 LZY 翻译为简体中文。 +[English Version 英文版本](README-EN.md) + +## 多语言支持 + +由 LZY 翻译为简体中文,目前已支持简体中文和英文。 欢迎加入更多语言的翻译 @@ -16,8 +20,6 @@ 'zh_CN' ``` -[English Version 英文版本](README-EN.md) - ## Yanderify现在被称为 first-order-wrapper ,以更准确地描述其功能。 由于这个项目已不再处于开发阶段,因此不会到处更改名称。然而,我开始更新我所有项目的文档以使它们更好,因此名称的更改是必要的。您仍然可以将该项目称为Yanderify,所有提到Yanderify的链接都将继续工作。更改 repo 名称会破坏指向此处的任何书签或链接,因此不会发生这种情况。旧文件如下。 diff --git a/README.md b/README.md index ea586cb..38097cc 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,22 @@ [Simplified Chinese version 简体中文版本](README-ZH.md) +## Multi-language support + +Simplified Chinese is now supported. Welcome to add more language translations. + +The way: + +Add `LANGUAGENAME.json` in the `Languages` directory and translate it to other languages. + +You can check the language name that Windows is using in the following ways: + +```python +>>> import locale +>>> locale.getdefaultlocale()[0] +'zh_CN' +``` + ## Yanderify is now known as first-order-wrapper to more accurately describe its function. Since this project is no longer in active development, the name won't be changed everywhere. However, I'm starting to update documentation on all of my projects to make them better, so the name change felt neccessary.