快速收敛 发表于 2025-5-16 12:26:39

manus+dp+豆包+trae+剪映生成小说动漫尝试--脱光了分享

本帖最后由 快速收敛 于 2025-5-16 11:47 编辑

根据不二分享的教程DeepSeek+番茄小说==一天一部短篇小说·月入3W的秘密!

看到月入3W,来了兴致,决定尝试弄弄。

首先里面讲到用番茄小说,懒得下,刚好最近manus开放注册,使用manus生成一步修仙类型的小说,由于积分不足,完整小说没有生成成功。不过没关系,我就使用小说第一章内容来制作视频。



第一章具体内容,并放入dp中生成简短的。

第一章 废物少年与神秘烘炉
夜凉如水,寒意刺骨。残月如一弯冰冷的镰刀,无力地悬挂在墨色的天穹,稀疏的星光如同被冻结的泪珠, 无力地洒落在落云镇林家寂静的后山。

林辰蜷缩在一块棱角分明的巨石之后,身体的每一处都在叫嚣着剧痛。他紧咬着牙关,努力不让自己发出一丝懦弱的呻吟,尽管那深入骨髓的疼痛几乎要将他的意志碾碎。冰冷的夜风如同无形的鬼爪,一次次穿透他单薄的衣衫,带走他身上本就所剩无几的暖意,也让身上的伤口愈发狰狞可怖。嘴角残留的血迹早已凝固,变成了暗红色,映衬着他苍白而倔强的脸庞。

“林海!林豹!你们这群仗势欺人的狗东西!今日之辱,我林辰他日必百倍奉还!”林辰在心中无声地咆哮,每一个字都充满了血与泪。白日里在演武场上被同族子弟肆意欺凌的画面,如同梦魇般在他脑海中反复回放。林海那张扭曲而得意的脸,林豹那充满鄙夷的眼神,以及周围那些族人冷漠的、甚至带着几分幸灾乐祸的目光,都像一根根淬毒的钢针,狠狠扎在他的心上,让他痛不欲生。

他,林辰,林家旁系子弟,一个连父母是谁都只剩下模糊记忆的孤儿。在这个以武道为尊,血脉天赋决定一切的灵源大陆,他却像是被上天遗弃的敝履。灵根驳杂不堪,资质平庸至极,自小便被冠以“林家第一废物”的恶名。整整十六年,他耗费了无数心血,日夜苦修,却依旧死死地卡在炼体三重这个可悲的境界,连家族中最粗浅的入门拳法《碎石拳》都使得有气无力,软绵绵得像是在给敌人挠痒。他早已成为了整个落云镇街头巷尾的笑柄,是人们茶余饭后用来消遣的谈资。

今天,他又因为一件微不足道的小事——仅仅是在修炼时无意中挡了林海的路——便被那群嫡系子弟堵在演武场,当着众人的面,进行了一场单方面的、极尽羞辱的殴打。若非一位平日里对他还算有几分怜悯的老执事恰巧路过,出言喝止,恐怕他今天就要被那群畜生生生打死在演武场上,落得个尸骨无存的下场。

“力量……我需要力量!我渴望拥有撕裂一切不公的力量!”林辰用尽全身力气,一拳狠狠地砸在身下的巨石之上。指节瞬间皮开肉绽,碎裂的骨骼传来阵阵钻心的剧痛,但他仿佛感觉不到一般,任由温热的鲜血染红了冰冷的石面。在这个残酷的世界上,没有实力,就意味着任人宰割,就意味着连最基本的尊严都如同风中残烛,随时可能被无情地吹灭。他不想再过这种猪狗不如的日子!他不想再看到任何人鄙夷的目光!

他颤抖着手,从早已破旧不堪的衣衫内袋中,摸出一块通体漆黑、毫不起眼的鹅卵石。这块石头约莫有婴儿拳头大小,表面粗糙,没有任何奇异之处,是他那对早已逝去的父母留给他的唯一遗物。自他记事起,这块石头便一直佩戴在他身上,承载了他对双亲所有的模糊思念与孺慕之情。他曾无数次在孤寂绝望的夜晚,将所有的希望都寄托在这块冰冷的石头上,一遍遍地幻想它是什么隐藏于世的绝世宝贝,能够助他脱胎换骨,逆天改命,摆脱这令人窒息的“废物”命运。然而,现实一次又一次地将他幼稚的幻想无情击碎。这块石头,除了比寻常的石头更加坚硬一些,似乎真的没有任何特异之处。

“爹……娘……”林辰的声音哽咽了,积压在心中多年的委屈与不甘在这一刻如同决堤的洪水般汹涌而出。温热的泪水终于忍不住夺眶而出,混着嘴角的血迹,顺着他消瘦的脸颊无声滑落。“孩儿无能……不仅无法查明你们当年失踪的真相,为你们报仇雪恨,甚至连自己都保护不了,还要受这等奇耻大辱……让你们在九泉之下都不得安宁……我……我真是个天大的废物啊!”无尽的悲愤与绝望如同潮水般将他淹没,他将那块鹅卵石死死地攥在掌心,锋利的石棱深深地刺入皮肉,鲜血汩汩而出,染红了那块漆黑的石头,也浸湿了他心中最后一点微弱的希望之火。

就在这时,异变陡生!

那块被林辰鲜血浸染的黑色鹅卵石,毫无征兆地爆发出了一团濛濛的、深邃的乌光!那光芒并不刺眼,却仿佛蕴含着某种来自亘古洪荒的神秘力量。紧接着,一道道细密如蛛网般的裂纹,以肉眼可见的速度在石头表面迅速蔓延开来。“咔嚓”一声清脆的碎裂声响起,在寂静的夜空中显得格外清晰。那块陪伴了林辰十多年的鹅卵石,应声碎裂!

林辰被眼前这突如其来的一幕惊得目瞪口呆,甚至忘记了身上的疼痛。还没等他从震惊中回过神来,从那碎裂的鹅卵石核心之中,骤然射出了一缕细若游丝,却又仿佛蕴含着开天辟地般伟力的鸿蒙紫气!那紫气灵动异常,如同拥有生命一般,在空中划过一道玄奥的轨迹,瞬间便没入了林辰的眉心祖窍之中!

“呃啊——!”

一股难以用言语形容的剧痛,如同火山爆发般猛地在林辰的脑海中炸开!他感觉自己的脑袋仿佛要被一股无形的力量硬生生撕裂,灵魂像是被投入了一个正在熊熊燃烧的巨大熔炉之中,被反复锤炼、锻打、碾压。与此同时,无数玄奥繁复、晦涩难明的信息,如同决堤的洪流一般,疯狂地涌入他的意识海洋,冲击着他浅薄的认知,颠覆着他对这个世界的理解。

他仿佛看到了宇宙的诞生与毁灭,星辰的轮转与寂灭,万物的起源与终结……也仿佛看到了无数惊天动地的功法神通的奥秘,丹道阵法的无上精髓……这些信息是如此的浩瀚、如此的深邃,远非他一个小小的炼体三重修士所能理解和承受。

不知过了多久,或许只是一瞬,又或许是千百年。那股几乎要将他灵魂撕碎的剧痛,如同潮水般渐渐消退。取而代之的,是一种前所未有的清明与通透,仿佛整个世界在他眼中都变得不一样了。林辰缓缓睁开双眼,那双原本黯淡无光的眸子里,此刻不再是迷茫与不甘,而是充满了难以置信的震惊与难以抑制的狂喜。

在他的识海之中,一座古朴无华的青铜小鼎,正静静地悬浮在那里。鼎高约三寸,三足两耳,通体呈现出一种深沉的青黑色,仿佛经历了无尽岁月的洗礼。鼎身之上,布满了玄奥繁复、不可名状的道纹,每一个符文都仿佛蕴含着天地至理,散发着一股亘古苍凉、至高无上的气息。一股明悟,如同醍醐灌顶般涌上林辰的心头——此鼎,名为“大道烘炉”!

这便是那缕神秘的鸿蒙紫气所化的无上异宝,拥有着解析万法根源,完美推演功法,加速悟道修行等等不可思议的神奇能力!

“大道烘炉……”林辰心念微微一动,尝试着在脑海中回忆家族那部粗浅不堪的基础功法《碎石拳》的修炼法门。

刹那之间,他识海中那座古朴的青铜小鼎微微一震,鼎口处射出一道柔和的微光,瞬间便将《碎石拳》的所有修炼法门尽数笼罩。紧接着,林辰的脑海中便如同醍醐灌顶一般,清晰无比地浮现出《碎石拳》的每一处运气路线,每一分发力技巧,甚至连其中存在的几处细微的缺陷和可以改进的地方,都以一种他从未想象过的方式,完美地呈现在他的面前!

“原来是这样……这《碎石拳》的发力方式太过粗糙,简直是暴殄天物!若是将这几处关键经脉的灵力运转轨迹稍作调整,再配合这种独特的呼吸法门,其威力至少能提升三成以上!不,甚至可能达到五成!”林辰心中豁然开朗,仿佛一瞬间打开了一扇通往全新世界的大门。以往那些困扰他许久,百思不得其解的修炼难题,在“大道烘炉”的解析之下,都变得如此简单明了。

他几乎是迫不及待地从地上翻身而起,强忍着身上的伤痛,按照“大道烘炉”推演出的完美版本《碎石拳》开始修炼。原本在他看来晦涩难懂、难以掌握的运气法门,此刻在他眼中却变得简单得如同呼吸一般自然。体内那本就稀薄的灵力,此刻却以前所未有的顺畅姿态,在他经过优化的经脉中飞速流转。每一次出拳,都带着一股以往从未有过的凌厉劲风,拳风呼啸,隐隐有破空之声!

“呼……哈!”

林辰一遍又一遍地演练着,完全沉浸在这种奇妙的感觉之中,甚至忘记了时间的流逝和身上的伤痛。他能清晰地感觉到,自己的力量在一点一滴地增强,对拳法的理解也在以一种不可思议的速度飞速提升。

仅仅一个时辰之后,他便将这套经过“大道烘炉”完美优化的《碎石拳》,修炼到了炉火纯青、登堂入室的大成境界!这在以前,是他连做梦都不敢想象的事情!要知道,家族中那些所谓的天才,将这套基础拳法修炼到大成,也至少需要数月之功!

“炼体三重巅峰……不,似乎已经隐隐触摸到炼体四重的壁垒了!”林辰收拳而立,仔细感受着体内那股远比之前充盈了数倍的力量,以及丹田中那颗微微壮大了一圈的灵力种子,脸上露出了难以置信的狂喜之色。

这“大道烘炉”,简直就是为他量身打造的逆天外挂!有了它,何愁不能摆脱废物的名头?何愁不能将那些曾经欺辱他、嘲笑他的人狠狠踩在脚下?

他深吸一口气,努力平复下因为过度激动而剧烈起伏的心情。他知道,从今天起,他林辰的命运,将因为这“大道烘炉”的出现,而发生翻天覆地的改变!那些曾经高高在上,视他如蝼蚁的家伙们,终将为他们的所作所为,付出惨重的代价!

“林海,林豹……还有林家那些看不起我的人,你们给我等着!我们很快就会再见面的!”林辰的眼中闪过一丝冰冷的寒芒,嘴角却勾起了一抹充满了自信与期待的笑容。

夜色依旧深沉,寒风依旧凛冽。但林辰的心中,却已然升起了一轮足以照亮整个黑暗的骄阳。他的修仙之路,从这一刻起,才算真正开始!而这座神秘莫测的“大道烘炉”,必将成为他在这波澜壮阔、危机四伏的修仙世界之中,披荆斩棘,逆天改命,最终登临绝顶的,最大、也是最可靠的依仗!

要求:提取抖音里的爆款逻辑,将上面这章篇幅润色控制在2000字左右。
开始也是按教程,让dp生成分镜,但是复制到剪映里面发现并不需要分镜,只需要故事就行。由于剪映只支持3000字故事成片,所以这里我让dp修改为2000字左右,但实际返回的内容只有500多字。以下是dp返回的结果:
残月如钩,林辰蜷缩在后山裂石后。鲜血从十七道伤口渗出,在零下寒气中凝成冰渣。

"林家嫡系的狗,今日之辱必百倍偿还!"少年染血的指甲深深抠进冻土。三小时前,他因挡了林海的路,被当众扒光上衣鞭笆——这是今年第七次羞辱直播。

作为林家著名废柴,16岁卡在炼体三重。而嫡系子弟林海,上月刚突破炼体七重。

"废物就该像蛆虫爬行!"记忆里林海踩着他头颅狞笑,四周传来嫡系子弟的哄笑。最刺痛的是远处白衣少女的目光——那个曾与他青梅竹马的林家大小姐林清雪,此刻正冷漠地擦拭佩剑。

突然,贴身十六年的黑卵石发出灼热。这是父母唯一遗物,此刻竟吸饱鲜血开始龟裂。

"轰!"

紫光炸裂的瞬间,林辰瞳孔收缩。他看到宇宙坍缩成青铜鼎纹,洪荒道音在脑内轰鸣:【大道烘炉激活,可解析万法本源】

剧痛中,家族《碎石拳》自动分解重构——

"原来第三式气走天枢是错的!"林辰颤抖着挥拳,空气竟发出爆鸣。原本需要蓄力三秒的招式,如今0.3秒就能轰出!

体内灵力疯狂奔涌,停滞三年的境界开始松动。当青铜鼎纹在识海显现时,少年浑身骨节爆响,炼体四重的气息震碎周身冰霜。

"林海,七日后族比..."他撕下染血衣襟系在眼上,嘴角咧开癫狂弧度:"我要你跪着舔干净演武场!"

复制到剪映故事成片,发现成片只有免费一次额度,需要开通svip,为了测试,想着月入3w,忍痛不小心开通了一个月的svip{:10_256:}

开通后,就可以愉快的生成视频了{:10_254:} ,但是也只有3000多积分,并且一个月会清零,那就不能浪费了。

开始制作视频.............{:9_236:} ,我的月入3W等着我......




选择文案:刚生成的内容
选择风格:仙侠古风
分镜素材:智能分镜,这里有两种,图片分镜和智能分镜,图片分镜,根据内容只生成图片。智能分镜会将图片转化为视频,经测试,只有部分分镜转化为动态视频,大部分分镜还是图片。:
配音:按自己喜好,我选择的是古风男主
语速:默认
背景音乐:智能推荐
视频比例:我选择16:9

开始生成视频,等待结果.....................{:9_236:}

生成完毕后,发现视频少了点东西,缺那么一点意思,那就是封面,视频里面截取的画面做封面体现不了第一章的主题,好吧,那就生成一个吧,找找发现豆包生成图片还不错,这里我使用豆包生成图片,如图


我选择了第一张{:9_217:} 。

但是在剪映里面剪辑,发现封面是不是动态一点要帅一点,毕竟男人嘛,耍帅最重要!{:9_217:}

找来找去,豆包也可以图片视频化,那就继续用豆包生成吧,如图


完美生成,效果也还不错,但是有水印,这是什么鬼......

好吧,那就去掉水印{:10_265:} ,不会怎么办,当然是找AI来帮忙

这里寻求AI的帮忙,让AI帮忙生成去水印的代码,利用tare工具生成python代码:

这是文件watermark_remover_gui.py
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import os
import threading
import cv2
from watermark_remover import VideoWatermarkRemover

class VideoWatermarkRemoverGUI:
    def __init__(self, root):
      self.root = root
      self.root.title("视频去水印工具")
      self.root.geometry("600x400")
      self.root.resizable(True, True)
      
      # 设置样式
      self.style = ttk.Style()
      self.style.configure("TButton", font=("Arial", 10))
      self.style.configure("TLabel", font=("Arial", 10))
      
      # 创建主框架
      main_frame = ttk.Frame(root, padding="10")
      main_frame.pack(fill=tk.BOTH, expand=True)
      
      # 输入视频选择
      input_frame = ttk.Frame(main_frame)
      input_frame.pack(fill=tk.X, pady=5)
      
      ttk.Label(input_frame, text="输入视频:").pack(side=tk.LEFT, padx=5)
      self.input_path_var = tk.StringVar()
      ttk.Entry(input_frame, textvariable=self.input_path_var, width=50).pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
      ttk.Button(input_frame, text="浏览...", command=self.browse_input).pack(side=tk.LEFT, padx=5)
      
      # 输出视频选择
      output_frame = ttk.Frame(main_frame)
      output_frame.pack(fill=tk.X, pady=5)
      
      ttk.Label(output_frame, text="输出视频:").pack(side=tk.LEFT, padx=5)
      self.output_path_var = tk.StringVar()
      ttk.Entry(output_frame, textvariable=self.output_path_var, width=50).pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
      ttk.Button(output_frame, text="浏览...", command=self.browse_output).pack(side=tk.LEFT, padx=5)
      
      # 水印区域设置
      region_frame = ttk.Frame(main_frame)
      region_frame.pack(fill=tk.X, pady=5)
      
      ttk.Label(region_frame, text="水印区域:").pack(side=tk.LEFT, padx=5)
      
      # 创建水印区域输入框
      coords_frame = ttk.Frame(region_frame)
      coords_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)
      
      # X坐标
      x_frame = ttk.Frame(coords_frame)
      x_frame.pack(side=tk.LEFT, padx=2)
      ttk.Label(x_frame, text="X:").pack(side=tk.LEFT)
      self.x_var = tk.StringVar()
      ttk.Entry(x_frame, textvariable=self.x_var, width=5).pack(side=tk.LEFT)
      
      # Y坐标
      y_frame = ttk.Frame(coords_frame)
      y_frame.pack(side=tk.LEFT, padx=2)
      ttk.Label(y_frame, text="Y:").pack(side=tk.LEFT)
      self.y_var = tk.StringVar()
      ttk.Entry(y_frame, textvariable=self.y_var, width=5).pack(side=tk.LEFT)
      
      # 宽度
      w_frame = ttk.Frame(coords_frame)
      w_frame.pack(side=tk.LEFT, padx=2)
      ttk.Label(w_frame, text="宽:").pack(side=tk.LEFT)
      self.w_var = tk.StringVar()
      ttk.Entry(w_frame, textvariable=self.w_var, width=5).pack(side=tk.LEFT)
      
      # 高度
      h_frame = ttk.Frame(coords_frame)
      h_frame.pack(side=tk.LEFT, padx=2)
      ttk.Label(h_frame, text="高:").pack(side=tk.LEFT)
      self.h_var = tk.StringVar()
      ttk.Entry(h_frame, textvariable=self.h_var, width=5).pack(side=tk.LEFT)
      
      # 自动检测选项
      self.auto_detect_var = tk.BooleanVar(value=True)
      ttk.Checkbutton(region_frame, text="自动检测", variable=self.auto_detect_var,
                     command=self.toggle_region_inputs).pack(side=tk.LEFT, padx=5)
      
      # 视频尺寸信息
      video_info_frame = ttk.Frame(main_frame)
      video_info_frame.pack(fill=tk.X, pady=5)
      ttk.Label(video_info_frame, text="视频尺寸:").pack(side=tk.LEFT, padx=5)
      self.video_size_var = tk.StringVar(value="未加载")
      ttk.Label(video_info_frame, textvariable=self.video_size_var).pack(side=tk.LEFT, padx=5)
      
      # 预览按钮
      preview_frame = ttk.Frame(main_frame)
      preview_frame.pack(fill=tk.X, pady=5)
      ttk.Button(preview_frame, text="预览水印区域", command=self.preview_watermark).pack(side=tk.LEFT, padx=5)
      ttk.Button(preview_frame, text="鼠标框选水印", command=self.select_watermark_by_mouse).pack(side=tk.LEFT, padx=5)
      
      # 进度条
      progress_frame = ttk.Frame(main_frame)
      progress_frame.pack(fill=tk.X, pady=10)
      ttk.Label(progress_frame, text="处理进度:").pack(side=tk.LEFT, padx=5)
      self.progress_var = tk.DoubleVar()
      self.progress_bar = ttk.Progressbar(progress_frame, variable=self.progress_var, length=100, mode="determinate")
      self.progress_bar.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
      
      # 状态标签
      self.status_var = tk.StringVar(value="就绪")
      status_label = ttk.Label(main_frame, textvariable=self.status_var)
      status_label.pack(fill=tk.X, pady=5)
      
      # 按钮框架
      button_frame = ttk.Frame(main_frame)
      button_frame.pack(fill=tk.X, pady=10)
      
      # 开始处理按钮
      self.process_button = ttk.Button(button_frame, text="开始处理", command=self.start_processing)
      self.process_button.pack(side=tk.RIGHT, padx=5)
      
      # 初始化状态
      self.processing = False
      self.toggle_region_inputs()
   
    def toggle_region_inputs(self):
      """启用或禁用水印区域输入框"""
      state = "disabled" if self.auto_detect_var.get() else "normal"
      for entry_var in :
            for child in self.root.winfo_children():
                self._set_state(child, entry_var, state)
   
    def _set_state(self, parent, var, state):
      """递归设置控件状态"""
      for child in parent.winfo_children():
            if hasattr(child, 'textvariable') and child.textvariable == var:
                child.configure(state=state)
            self._set_state(child, var, state)
   
    def browse_input(self):
      """浏览选择输入视频文件"""
      file_path = filedialog.askopenfilename(
            title="选择输入视频",
            filetypes=[("视频文件", "*.mp4 *.avi *.mov *.mkv"), ("所有文件", "*.*")]
      )
      if file_path:
            self.input_path_var.set(file_path)
            # 自动设置输出路径
            base, ext = os.path.splitext(file_path)
            self.output_path_var.set(f"{base}_无水印{ext}")
            
            # 尝试获取视频尺寸
            try:
                cap = cv2.VideoCapture(file_path)
                if cap.isOpened():
                  remover = VideoWatermarkRemover(file_path, "", None)
                  width, height = remover.get_video_dimensions(cap)
                  self.video_size_var.set(f"{width} × {height}")
                  cap.release()
                else:
                  self.video_size_var.set("无法获取尺寸")
            except Exception:
                self.video_size_var.set("无法获取尺寸")
   
    def browse_output(self):
      """浏览选择输出视频文件"""
      file_path = filedialog.asksaveasfilename(
            title="保存输出视频",
            filetypes=[("MP4视频", "*.mp4"), ("AVI视频", "*.avi"), ("所有文件", "*.*")],
            defaultextension=".mp4"
      )
      if file_path:
            self.output_path_var.set(file_path)
   
    def preview_watermark(self):
      """预览水印区域"""
      input_path = self.input_path_var.get()
      if not input_path or not os.path.isfile(input_path):
            messagebox.showerror("错误", "请先选择有效的输入视频文件")
            return
      
      try:
            # 打开视频并读取第一帧
            cap = cv2.VideoCapture(input_path)
            if not cap.isOpened():
                messagebox.showerror("错误", f"无法打开视频文件: {input_path}")
                return
               
            ret, frame = cap.read()
            if not ret:
                messagebox.showerror("错误", "无法读取视频帧")
                cap.release()
                return
            
            # 创建临时的去水印器
            remover = VideoWatermarkRemover(input_path, "", None)
            
            # 获取并显示视频尺寸
            width, height = remover.get_video_dimensions(cap)
            self.video_size_var.set(f"{width} × {height}")
            
            # 如果选择自动检测,尝试检测水印区域
            if self.auto_detect_var.get():
                self.status_var.set("正在检测水印区域...")
                self.root.update()
               
                region = remover._detect_watermark(cap)
               
                if region is None:
                  messagebox.showwarning("警告", "无法自动检测水印区域,请手动指定")
                  self.auto_detect_var.set(False)
                  self.toggle_region_inputs()
                else:
                  # 更新UI中的区域值
                  self.x_var.set(str(region))
                  self.y_var.set(str(region))
                  self.w_var.set(str(region))
                  self.h_var.set(str(region))
            
            # 获取水印区域
            try:
                x = int(self.x_var.get())
                y = int(self.y_var.get())
                w = int(self.w_var.get())
                h = int(self.h_var.get())
                region =
            except ValueError:
                if not self.auto_detect_var.get():
                  messagebox.showerror("错误", "请输入有效的水印区域坐标")
                  cap.release()
                  return
                region = None
            
            if region:
                # 在帧上绘制水印区域
                x, y, w, h = region
                cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)
               
                # 在预览图像上显示尺寸信息
                info_text = f"视频尺寸: {width} × {height}, 水印区域: [{x}, {y}, {w}, {h}]"
                cv2.putText(frame, info_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
               
                # 显示预览
                cv2.imshow("水印区域预览", frame)
                cv2.waitKey(0)
                cv2.destroyAllWindows()
            
            cap.release()
            self.status_var.set("就绪")
            
      except Exception as e:
            messagebox.showerror("错误", f"预览时发生错误: {str(e)}")
            self.status_var.set("就绪")
            
    def select_watermark_by_mouse(self):
      """使用鼠标框选水印区域"""
      input_path = self.input_path_var.get()
      if not input_path or not os.path.isfile(input_path):
            messagebox.showerror("错误", "请先选择有效的输入视频文件")
            return
      
      try:
            # 打开视频并读取第一帧
            cap = cv2.VideoCapture(input_path)
            if not cap.isOpened():
                messagebox.showerror("错误", f"无法打开视频文件: {input_path}")
                return
               
            ret, frame = cap.read()
            if not ret:
                messagebox.showerror("错误", "无法读取视频帧")
                cap.release()
                return
            
            # 创建临时的去水印器
            remover = VideoWatermarkRemover(input_path, "", None)
            
            # 获取并显示视频尺寸
            width, height = remover.get_video_dimensions(cap)
            self.video_size_var.set(f"{width} × {height}")
            
            # 创建一个窗口和鼠标回调函数
            window_name = "框选水印区域 (按住鼠标左键拖动选择,按ESC取消,按Enter确认)"
            cv2.namedWindow(window_name)
            
            # 标记窗口是否已关闭
            self.window_closed = False
            
            # 添加窗口关闭事件处理
            def on_window_close(*args):
                self.window_closed = True
            
            # 设置窗口关闭回调
            cv2.setWindowProperty(window_name, cv2.WND_PROP_TOPMOST, 1)
            
            # 初始化鼠标选择变量
            self.mouse_selecting = False
            self.selection_start = (-1, -1)
            self.selection_end = (-1, -1)
            self.current_frame = frame.copy()
            
            # 定义鼠标回调函数
            def mouse_callback(event, x, y, flags, param):
                if event == cv2.EVENT_LBUTTONDOWN:
                  # 开始选择
                  self.mouse_selecting = True
                  self.selection_start = (x, y)
                  self.selection_end = (x, y)
               
                elif event == cv2.EVENT_MOUSEMOVE and self.mouse_selecting:
                  # 更新选择区域
                  self.selection_end = (x, y)
               
                elif event == cv2.EVENT_LBUTTONUP:
                  # 完成选择
                  self.mouse_selecting = False
                  self.selection_end = (x, y)
               
                # 绘制选择框
                img_copy = frame.copy()
                if self.selection_start != (-1, -1) and self.selection_end != (-1, -1):
                  start_x, start_y = self.selection_start
                  end_x, end_y = self.selection_end
                  
                  # 确保坐标有序
                  x1, x2 = min(start_x, end_x), max(start_x, end_x)
                  y1, y2 = min(start_y, end_y), max(start_y, end_y)
                  
                  # 绘制矩形
                  cv2.rectangle(img_copy, (x1, y1), (x2, y2), (0, 0, 255), 2)
                  
                  # 显示坐标信息
                  w, h = x2 - x1, y2 - y1
                  info_text = f"选择区域: [{x1}, {y1}, {w}, {h}]"
                  cv2.putText(img_copy, info_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
               
                self.current_frame = img_copy
                cv2.imshow(window_name, self.current_frame)
            
            # 设置鼠标回调
            cv2.setMouseCallback(window_name, mouse_callback)
            
            # 显示初始帧
            cv2.imshow(window_name, frame)
            
            # 等待用户操作
            while True:
                # 检查窗口是否存在
                if self.window_closed or cv2.getWindowProperty(window_name, cv2.WND_PROP_VISIBLE) < 1:
                  break
                  
                cv2.imshow(window_name, self.current_frame)
                key = cv2.waitKey(1) & 0xFF
               
                # 按ESC取消
                if key == 27:# ESC键
                  break
               
                # 按Enter确认
                if key == 13:# Enter键
                  if self.selection_start != (-1, -1) and self.selection_end != (-1, -1):
                        start_x, start_y = self.selection_start
                        end_x, end_y = self.selection_end
                        
                        # 确保坐标有序
                        x1, x2 = min(start_x, end_x), max(start_x, end_x)
                        y1, y2 = min(start_y, end_y), max(start_y, end_y)
                        
                        # 计算宽高
                        w, h = x2 - x1, y2 - y1
                        
                        # 更新UI中的坐标值
                        self.x_var.set(str(x1))
                        self.y_var.set(str(y1))
                        self.w_var.set(str(w))
                        self.h_var.set(str(h))
                        
                        # 如果自动检测被选中,取消它
                        if self.auto_detect_var.get():
                            self.auto_detect_var.set(False)
                            self.toggle_region_inputs()
                        
                        # 先关闭所有OpenCV窗口,再显示消息框
                        cv2.destroyAllWindows()
                        cap.release()
                        self.status_var.set("就绪")
                        messagebox.showinfo("成功", f"已选择水印区域: [{x1}, {y1}, {w}, {h}]")
                        return# 直接返回,避免重复执行后面的清理代码
                  else:
                        messagebox.showwarning("警告", "请先框选一个区域")
            
            # 清理
            cv2.destroyAllWindows()
            cap.release()
            self.status_var.set("就绪")
            
      except Exception as e:
            messagebox.showerror("错误", f"框选水印区域时发生错误: {str(e)}")
            self.status_var.set("就绪")
   
    def start_processing(self):
      """开始处理视频"""
      if self.processing:
            messagebox.showinfo("提示", "正在处理中,请等待完成")
            return
            
      input_path = self.input_path_var.get()
      output_path = self.output_path_var.get()
      
      # 验证输入
      if not input_path or not os.path.isfile(input_path):
            messagebox.showerror("错误", "请选择有效的输入视频文件")
            return
            
      if not output_path:
            messagebox.showerror("错误", "请指定输出视频文件路径")
            return
            
      # 获取水印区域
      region = None
      if not self.auto_detect_var.get():
            try:
                x = int(self.x_var.get())
                y = int(self.y_var.get())
                w = int(self.w_var.get())
                h = int(self.h_var.get())
                region =
            except ValueError:
                messagebox.showerror("错误", "请输入有效的水印区域坐标")
                return
      
      # 确保输出目录存在
      output_dir = os.path.dirname(output_path)
      if output_dir and not os.path.exists(output_dir):
            try:
                os.makedirs(output_dir)
            except Exception as e:
                messagebox.showerror("错误", f"无法创建输出目录: {str(e)}")
                return
      
      # 开始处理线程
      self.processing = True
      self.process_button.configure(state="disabled")
      self.progress_var.set(0)
      self.status_var.set("正在处理视频...")
      
      thread = threading.Thread(target=self._process_video, args=(input_path, output_path, region))
      thread.daemon = True
      thread.start()
   
    def _process_video(self, input_path, output_path, region):
      """在后台线程中处理视频"""
      try:
            # 创建进度回调函数
            def progress_callback(current, total):
                progress = (current / total) * 100
                self.progress_var.set(progress)
                self.status_var.set(f"正在处理视频... {current}/{total} 帧 ({progress:.1f}%)")
                self.root.update_idletasks()
            
            # 创建去水印器并处理
            remover = VideoWatermarkRemover(input_path, output_path, region)
            remover.set_progress_callback(progress_callback)
            success = remover.process()
            
            # 更新UI
            if success:
                self.status_var.set(f"处理完成,已保存到: {output_path}")
                messagebox.showinfo("完成", f"视频处理完成,已保存到:\n{output_path}")
            else:
                self.status_var.set("处理失败")
      except Exception as e:
            self.status_var.set(f"处理出错: {str(e)}")
            messagebox.showerror("错误", f"处理视频时发生错误:\n{str(e)}")
      finally:
            self.processing = False
            self.process_button.configure(state="normal")
            self.root.update_idletasks()


def main():
    root = tk.Tk()
    app = VideoWatermarkRemoverGUI(root)
    root.mainloop()


if __name__ == "__main__":
    main()

这是文件watermark_remover.py
import cv2
import numpy as np
import argparse
import os

class VideoWatermarkRemover:
    def __init__(self, input_path, output_path, watermark_region=None):
      """
      初始化视频去水印工具
      
      参数:
            input_path: 输入视频路径
            output_path: 输出视频路径
            watermark_region: 水印区域 ,如果为None则尝试自动检测
      """
      self.input_path = input_path
      self.output_path = output_path
      self.watermark_region = watermark_region
      self.progress_callback = None
      
    def set_progress_callback(self, callback):
      """
      设置进度回调函数
      
      参数:
            callback: 回调函数,接受两个参数 (current_frame, total_frames)
      """
      self.progress_callback = callback
      
    def process(self):
      """
      处理视频并去除水印
      """
      # 打开输入视频
      cap = cv2.VideoCapture(self.input_path)
      if not cap.isOpened():
            raise ValueError(f"无法打开视频文件: {self.input_path}")
            
      # 获取视频属性
      width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
      height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
      fps = cap.get(cv2.CAP_PROP_FPS)
      frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
      
      # 创建视频写入器
      fourcc = cv2.VideoWriter_fourcc(*'mp4v')
      out = cv2.VideoWriter(self.output_path, fourcc, fps, (width, height))
      
      # 如果没有指定水印区域,尝试自动检测
      if self.watermark_region is None:
            print("尝试自动检测水印区域...")
            self.watermark_region = self._detect_watermark(cap)
            cap.set(cv2.CAP_PROP_POS_FRAMES, 0)# 重置视频到开始位置
            
      if self.watermark_region is None:
            print("无法自动检测水印区域,请手动指定水印区域")
            return False
            
      print(f"处理视频中,水印区域: {self.watermark_region}")
      
      # 处理每一帧
      processed_frames = 0
      while True:
            ret, frame = cap.read()
            if not ret:
                break
               
            # 去除水印
            processed_frame = self._remove_watermark(frame)
            
            # 写入输出视频
            out.write(processed_frame)
            
            # 显示进度
            processed_frames += 1
            if processed_frames % 100 == 0:
                print(f"已处理 {processed_frames}/{frame_count} 帧 ({processed_frames/frame_count*100:.1f}%)")
               
            # 调用进度回调函数
            if self.progress_callback:
                self.progress_callback(processed_frames, frame_count)
      
      # 释放资源
      cap.release()
      out.release()
      print(f"视频处理完成,已保存到: {self.output_path}")
      return True
   
    def get_video_dimensions(self, cap):
      """
      获取视频尺寸
      
      参数:
            cap: 视频捕获对象
            
      返回:
            (width, height): 视频宽度和高度的元组
      """
      width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
      height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
      return (width, height)
   
    def _detect_watermark(self, cap):
      """
      尝试自动检测视频中的水印区域
      
      这里使用一个简单的方法:采样多个帧,找出帧之间变化较小的区域
      优先检测右下角区域作为水印位置
      """
      # 采样帧数
      sample_count = min(20, int(cap.get(cv2.CAP_PROP_FRAME_COUNT)))
      if sample_count < 3:
            return None
            
      # 获取视频尺寸
      width, height = self.get_video_dimensions(cap)
      
      # 采样帧
      frames = []
      frame_indices = np.linspace(0, cap.get(cv2.CAP_PROP_FRAME_COUNT) - 1, sample_count, dtype=int)
      
      for idx in frame_indices:
            cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
            ret, frame = cap.read()
            if ret:
                # 转换为灰度图
                gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                frames.append(gray)
      
      if len(frames) < 3:
            return None
            
      # 计算帧之间的差异
      diff_sum = np.zeros((height, width), dtype=np.float32)
      
      for i in range(len(frames) - 1):
            diff = cv2.absdiff(frames, frames)
            diff_sum += diff
            
      # 归一化差异图
      if np.max(diff_sum) > 0:
            diff_norm = diff_sum / np.max(diff_sum)
            diff_norm = (1.0 - diff_norm) * 255
            diff_norm = diff_norm.astype(np.uint8)
            
            # 二值化,找出变化较小的区域(可能是水印)
            _, thresh = cv2.threshold(diff_norm, 240, 255, cv2.THRESH_BINARY)
            
            # 形态学操作,去除噪点
            kernel = np.ones((5, 5), np.uint8)
            thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
            thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
            
            # 寻找轮廓
            contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
            
            # 筛选可能的水印区域(面积不太小,且位于图像边缘附近)
            min_area = width * height * 0.005# 最小面积阈值
            max_area = width * height * 0.15   # 最大面积阈值
            
            # 优先检查右下角区域的轮廓
            right_bottom_contours = []
            other_contours = []
            
            for contour in contours:
                area = cv2.contourArea(contour)
                if min_area < area < max_area:
                  x, y, w, h = cv2.boundingRect(contour)
                  # 检查是否在右下角
                  if x + w > width * 0.5 and y + h > height * 0.5:
                        right_bottom_contours.append((x, y, w, h, area))
                  # 检查是否靠近其他边缘
                  elif (x < width * 0.1 or x + w > width * 0.9 or
                        y < height * 0.1 or y + h > height * 0.9):
                        other_contours.append((x, y, w, h, area))
            
            # 优先返回右下角区域,按面积排序
            if right_bottom_contours:
                right_bottom_contours.sort(key=lambda c: c, reverse=True)
                return list(right_bottom_contours[:4])
            
            # 如果没有右下角区域,返回其他边缘区域
            if other_contours:
                other_contours.sort(key=lambda c: c, reverse=True)
                return list(other_contours[:4])
            
            # 如果没有检测到合适的水印区域,返回默认的右下角区域
            watermark_width = int(width * 0.2)# 默认水印宽度为视频宽度的20%
            watermark_height = int(height * 0.1)# 默认水印高度为视频高度的10%
            watermark_x = width - watermark_width - 10# 右边距离10像素
            watermark_y = height - watermark_height - 10# 下边距离10像素
            return
      
      return None
   
    def _remove_watermark(self, frame):
      """
      从帧中去除水印
      
      这里使用了一个简单的方法:使用Inpainting算法填充水印区域
      """
      if self.watermark_region is None:
            return frame
            
      # 创建掩码
      mask = np.zeros(frame.shape[:2], dtype=np.uint8)
      x, y, w, h = self.watermark_region
      mask = 255
      
      # 使用Inpainting算法填充水印区域
      result = cv2.inpaint(frame, mask, 3, cv2.INPAINT_TELEA)
      
      return result


def main():
    # 解析命令行参数
    parser = argparse.ArgumentParser(description='视频去水印工具')
    parser.add_argument('input', help='输入视频文件路径')
    parser.add_argument('output', help='输出视频文件路径')
    parser.add_argument('--region', type=int, nargs=4, metavar=('X', 'Y', 'WIDTH', 'HEIGHT'),
                        help='水印区域 ,如果不指定则尝试自动检测')
   
    args = parser.parse_args()
   
    # 检查输入文件是否存在
    if not os.path.isfile(args.input):
      print(f"错误: 输入文件不存在: {args.input}")
      return
      
    # 检查输出目录是否存在
    output_dir = os.path.dirname(args.output)
    if output_dir and not os.path.exists(output_dir):
      os.makedirs(output_dir)
   
    # 创建去水印器并处理
    remover = VideoWatermarkRemover(args.input, args.output, args.region)
    remover.process()


if __name__ == "__main__":
    main()

不得不说AI真滴强,经过几次AI修改,生成代码完全能运行。

将两份代码放在同一个文件夹下,运行watermark_remover_gui.py,如图



选择要去水印的视频,自动检测水印的位置,但其实检测不到,后来让AI来修改,添加鼠标框选水印的位置,点击处理。

测试水印能够去除掉{:10_275:} ,AI太强大了!

最后用剪映添加到视频开头,加一点特效,好了,展示结果吧:
https://www.bilibili.com/video/BV14UEWzkEQm/?share_source=copy_web&vd_source=6559b9d8c59a2bda01b6aede51637e7c

大家觉得这个视频怎么样?感觉有点意思{:10_254:}

不得不说剪映蛮强的,缺点是画面要能都是动态视频分镜就好了,另外如果后续章节能保持人物一致性那就最好了{:10_254:} ,这样能出连续章节性漫画了。

还有里面说到的创作者分成,我是没找到{:10_243:} ,后面再看看,看来赚钱与我无缘{:10_266:},我的月入3w啊...............{:10_266:}。

小甲鱼 发表于 2025-5-16 16:55:43

不错不错,待会来分享一下,值得大家学习~

不二如是 发表于 2025-5-16 15:01:58

牛!!

快速收敛 发表于 2025-5-16 15:03:22

不二如是 发表于 2025-5-16 15:01
牛!!

剪映牛!{:10_278:}

不二如是 发表于 2025-5-16 15:15:53

快速收敛 发表于 2025-5-16 15:03
剪映牛!

使用者更牛{:10_275:}

快速收敛 发表于 2025-5-16 15:18:46

不二如是 发表于 2025-5-16 15:15
使用者更牛

谢谢夸奖{:10_254:}

不二如是 发表于 2025-5-16 15:47:40

快速收敛 发表于 2025-5-16 15:18
谢谢夸奖

{:10_275:}鱼C有你更精彩{:10_288:}

快速收敛 发表于 2025-5-16 17:10:59

小甲鱼 发表于 2025-5-16 16:55
不错不错,待会来分享一下,值得大家学习~

{:10_254:}

qiuhan1987 发表于 2025-5-16 18:13:47

clollipops 发表于 2025-5-16 18:13:55

好一个脱光了分享

你的黄逗逗 发表于 2025-5-16 18:14:23

向学习挣外快

Pioneer. 发表于 2025-5-16 18:15:08

牛啊

每天提高一点点 发表于 2025-5-16 18:16:28

winnieGarden 发表于 2025-5-16 18:17:49

还能这么玩吗

lhhlyqly 发表于 2025-5-16 18:18:29

挣外快了

Referee_ZL 发表于 2025-5-16 18:19:20

月入三万啊~~~~~啊~~~~~

可惜不是真的,生成视频这个还是很强大的,可以用在很多地方!!用起来!加油!

xumingjie 发表于 2025-5-16 18:19:50

今年外快就看它了

科007 发表于 2025-5-16 18:19:59

学到了

13351890899 发表于 2025-5-16 18:21:05

打卡

maric123 发表于 2025-5-16 18:21:33

这外快有点技术要求的哇
页: [1] 2 3 4
查看完整版本: manus+dp+豆包+trae+剪映生成小说动漫尝试--脱光了分享