├── LICENSE ├── README.md └── 自动生成字幕.ipynb /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 zhenghao0379 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # autosubpy 2 | autosub,python 自动生成视频字幕并翻译 3 | -------------------------------------------------------------------------------- /自动生成字幕.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 自动生成字幕" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "工作内容:\n", 15 | "- 从视频文件自动生成外挂型字幕文件,不进行视频编辑等操作\n", 16 | "- 包括,时间轴\n", 17 | "\n", 18 | "\n", 19 | "主要工作:\n", 20 | "- 获取视频文件中的音频文件\n", 21 | "- 将音频文件分段\n", 22 | "- 采用IBM CLOUD进行语音转文字,每月500分钟免费\n", 23 | "- 自动构建B站字幕\n", 24 | "\n", 25 | "后续工作:\n", 26 | "- 采用 翻译API,自动进行初步翻译\n", 27 | " - google: googletrans包,因为墙pass\n", 28 | " - youdao: 翻译 api" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "## B站字幕文件 .bcc 格式" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 2, 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "data": { 45 | "text/plain": [ 46 | "{'font_size': 0.4,\n", 47 | " 'font_color': '#FFFFFF',\n", 48 | " 'background_alpha': 0.5,\n", 49 | " 'background_color': '#9C27B0',\n", 50 | " 'Stroke': 'none',\n", 51 | " 'body': [{'from': 13,\n", 52 | " 'to': 14.95,\n", 53 | " 'location': 2,\n", 54 | " 'content': 'Hi I`m Larry Bill'},\n", 55 | " {'from': 14.95,\n", 56 | " 'to': 18.825,\n", 57 | " 'location': 2,\n", 58 | " 'content': 'I`m chair guitar department Berklee College of Music'},\n", 59 | " {'from': 20.342341,\n", 60 | " 'to': 25.342341,\n", 61 | " 'location': 2,\n", 62 | " 'content': \"and it's my pleasure to \"}]}" 63 | ] 64 | }, 65 | "execution_count": 2, 66 | "metadata": {}, 67 | "output_type": "execute_result" 68 | } 69 | ], 70 | "source": [ 71 | "# 示例\n", 72 | "{\n", 73 | " \"font_size\":0.4, # 字体大小\n", 74 | " \"font_color\":\"#FFFFFF\", # 字体颜色\n", 75 | " \"background_alpha\":0.5, # 背景透明度 \n", 76 | " \"background_color\":\"#9C27B0\", # 背景颜色\n", 77 | " \"Stroke\":\"none\", # \n", 78 | " \"body\":[ # 主体\n", 79 | " {\n", 80 | " \"from\":13, # 起始处\n", 81 | " \"to\":14.95, # 结束处\n", 82 | " \"location\":2, # \n", 83 | " \"content\":\"Hi I`m Larry Bill\" # 主体\n", 84 | " },\n", 85 | " {\"from\":14.95,\"to\":18.825,\"location\":2,\"content\":\"I`m chair guitar department Berklee College of Music\"},\n", 86 | " {\"from\":20.342341,\"to\":25.342341,\"location\":2,\"content\":\"and it's my pleasure to work with you to \"}\n", 87 | " ]\n", 88 | "}" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "## 获取视频转音频" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 15, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "import moviepy.editor as mve" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": 27, 110 | "metadata": {}, 111 | "outputs": [ 112 | { 113 | "data": { 114 | "text/plain": [ 115 | "'D:\\\\Music\\\\电吉他\\\\Berklee - Modern Method for Guitar - Vol1 (DVD)\\\\video\\\\Lesson 1\\\\001.mov'" 116 | ] 117 | }, 118 | "execution_count": 27, 119 | "metadata": {}, 120 | "output_type": "execute_result" 121 | } 122 | ], 123 | "source": [ 124 | "path = r'D:\\Music\\电吉他\\Berklee - Modern Method for Guitar - Vol1 (DVD)\\video\\Lesson 1'\n", 125 | "\n", 126 | "file = '001.mov'\n", 127 | "\n", 128 | "filepath = path + \"\\\\\" + file\n", 129 | "\n", 130 | "filepath" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 21, 136 | "metadata": {}, 137 | "outputs": [], 138 | "source": [ 139 | "video = mve.VideoFileClip(filepath)\n", 140 | "audio = video.audio" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 22, 146 | "metadata": {}, 147 | "outputs": [ 148 | { 149 | "name": "stdout", 150 | "output_type": "stream", 151 | "text": [ 152 | "MoviePy - Writing audio in test.mp3\n" 153 | ] 154 | }, 155 | { 156 | "name": "stderr", 157 | "output_type": "stream", 158 | "text": [ 159 | " \r" 160 | ] 161 | }, 162 | { 163 | "name": "stdout", 164 | "output_type": "stream", 165 | "text": [ 166 | "MoviePy - Done.\n" 167 | ] 168 | } 169 | ], 170 | "source": [ 171 | "audio.write_audiofile('test.mp3')" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": null, 177 | "metadata": {}, 178 | "outputs": [], 179 | "source": [ 180 | "audio.write_audiofile('test.mp3')" 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": null, 186 | "metadata": {}, 187 | "outputs": [], 188 | "source": [ 189 | "# import ffmpeg\n", 190 | "# autosub,使用的时google 和 ffmpeg" 191 | ] 192 | }, 193 | { 194 | "cell_type": "markdown", 195 | "metadata": {}, 196 | "source": [ 197 | "## 音频转文字" 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "execution_count": null, 203 | "metadata": {}, 204 | "outputs": [], 205 | "source": [ 206 | "# IBM Cloud Speech to text\n", 207 | "# API密钥:-ijVpcr8DbYekYCkOEtalbfH6uMO1rI0qJAz0mEbDvre\n", 208 | "# URL:https://api.us-south.speech-to-text.watson.cloud.ibm.com/instances/48476942-3322-4bba-aae3-18a2b84015d7" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": {}, 215 | "outputs": [], 216 | "source": [] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "## 文字构成字幕" 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": null, 228 | "metadata": {}, 229 | "outputs": [], 230 | "source": [] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": null, 235 | "metadata": {}, 236 | "outputs": [], 237 | "source": [] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": {}, 243 | "outputs": [], 244 | "source": [] 245 | }, 246 | { 247 | "cell_type": "markdown", 248 | "metadata": {}, 249 | "source": [ 250 | "## 翻译" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 1, 256 | "metadata": {}, 257 | "outputs": [], 258 | "source": [ 259 | "# 工具包\n", 260 | "import requests\n", 261 | "import json" 262 | ] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "execution_count": 2, 267 | "metadata": {}, 268 | "outputs": [], 269 | "source": [ 270 | "# 有道翻译,调用有道翻译API(较不准,较快,稳定)\n", 271 | "def youdao_trans(text, t_type='AUTO'):\n", 272 | " text = text.replace(' ', '%20')\n", 273 | " url = 'http://fanyi.youdao.com/translate?&doctype=json&type='+t_type+'&i='+text\n", 274 | "# print(url)\n", 275 | " header = {}\n", 276 | " out = requests.get(url)\n", 277 | " out_json = out.json()\n", 278 | "# print(out_json)\n", 279 | " out_tgt = out_json['translateResult'][0][0]['tgt']\n", 280 | "# print(out_tgt)\n", 281 | " return out_tgt" 282 | ] 283 | }, 284 | { 285 | "cell_type": "code", 286 | "execution_count": 25, 287 | "metadata": {}, 288 | "outputs": [ 289 | { 290 | "data": { 291 | "text/plain": [ 292 | "'我的吉他在伯克利音乐学院'" 293 | ] 294 | }, 295 | "execution_count": 25, 296 | "metadata": {}, 297 | "output_type": "execute_result" 298 | } 299 | ], 300 | "source": [ 301 | "# test\n", 302 | "youdao_trans(\"I'm chair of the guitar department here at Berklee college of music\")" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 6, 308 | "metadata": {}, 309 | "outputs": [], 310 | "source": [ 311 | "# 谷歌翻译_1,调用谷歌翻译(较准,较慢,超时)\n", 312 | "from googletrans import Translator\n", 313 | "translator = Translator(service_urls=['translate.google.cn'])\n", 314 | "\n", 315 | "def google_trans0(text, dest='zh-cn'):\n", 316 | " try :\n", 317 | " out = translator.translate(text, dest=dest).text\n", 318 | " return out\n", 319 | " except:\n", 320 | " return '翻译异常'" 321 | ] 322 | }, 323 | { 324 | "cell_type": "code", 325 | "execution_count": 26, 326 | "metadata": {}, 327 | "outputs": [ 328 | { 329 | "data": { 330 | "text/plain": [ 331 | "'我是吉他系主任这里伯克利音乐学院'" 332 | ] 333 | }, 334 | "execution_count": 26, 335 | "metadata": {}, 336 | "output_type": "execute_result" 337 | } 338 | ], 339 | "source": [ 340 | "# test\n", 341 | "google_trans0(\"I'm chair of the guitar department here at Berklee college of music\")" 342 | ] 343 | }, 344 | { 345 | "cell_type": "code", 346 | "execution_count": 28, 347 | "metadata": {}, 348 | "outputs": [], 349 | "source": [ 350 | "text = \"After you're done with this book and actually while you're playing this book you will develop a sense of musicality you'll develop strength in your hands you'll develop a sense of time with the chords a sense of melody and you'll just get better as a guitarist and as a musician.\"" 351 | ] 352 | }, 353 | { 354 | "cell_type": "code", 355 | "execution_count": 29, 356 | "metadata": {}, 357 | "outputs": [ 358 | { 359 | "data": { 360 | "text/plain": [ 361 | "'之后你完成这本书,当你玩这本书你将开发一种音乐性发展力量在你的手你会开发一个意义上的时间与和弦的旋律,你会得到更好的吉他手和一个音乐家。'" 362 | ] 363 | }, 364 | "execution_count": 29, 365 | "metadata": {}, 366 | "output_type": "execute_result" 367 | } 368 | ], 369 | "source": [ 370 | "youdao_trans(text)" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": null, 376 | "metadata": {}, 377 | "outputs": [], 378 | "source": [ 379 | "google_trans0(text)" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "execution_count": 8, 385 | "metadata": {}, 386 | "outputs": [], 387 | "source": [ 388 | "# 谷歌翻译_2,调用网页版(准)\n", 389 | "# 构建中,tk解密破解\n", 390 | "def google_trans(text, sl='auto', tl='zh_CN'):\n", 391 | " text = text.replace(' ', '%20')\n", 392 | " url = 'http://translate.google.cn/translate_a/single?client=t&dt=t&dj=1&ie=UTF-8&sl='+sl+'%tl='+tl+'&q='+text\n", 393 | " print(url)\n", 394 | " header = {}\n", 395 | " out = requests.get(url)\n", 396 | " out_json = out.json()\n", 397 | " print(out_json)\n", 398 | " out_tgt = out_json['translateResult'][0][0]['tgt']\n", 399 | " print(out_tgt)\n", 400 | " return out_tgt" 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": null, 406 | "metadata": {}, 407 | "outputs": [], 408 | "source": [ 409 | "# test\n", 410 | "# google_trans2('guitar department berklee college of music')" 411 | ] 412 | }, 413 | { 414 | "cell_type": "code", 415 | "execution_count": null, 416 | "metadata": {}, 417 | "outputs": [], 418 | "source": [] 419 | } 420 | ], 421 | "metadata": { 422 | "kernelspec": { 423 | "display_name": "Python 3", 424 | "language": "python", 425 | "name": "python3" 426 | }, 427 | "language_info": { 428 | "codemirror_mode": { 429 | "name": "ipython", 430 | "version": 3 431 | }, 432 | "file_extension": ".py", 433 | "mimetype": "text/x-python", 434 | "name": "python", 435 | "nbconvert_exporter": "python", 436 | "pygments_lexer": "ipython3", 437 | "version": "3.7.4" 438 | } 439 | }, 440 | "nbformat": 4, 441 | "nbformat_minor": 2 442 | } 443 | --------------------------------------------------------------------------------