Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save me-suzy/af81e7766002e5a33d2c4e61b5619d99 to your computer and use it in GitHub Desktop.
Save me-suzy/af81e7766002e5a33d2c4e61b5619d99 to your computer and use it in GitHub Desktop.
ChatGPT BUN tanar - adaugare text si voce video peste vechea voce
import os
from moviepy.editor import VideoFileClip, AudioFileClip, concatenate_audioclips, AudioClip, TextClip, CompositeVideoClip
from moviepy.config import change_settings
from pydub import AudioSegment
import openai
import tempfile
import time
# Configurare pentru ffmpeg
os.environ["PATH"] += os.pathsep + r"D:\ffmpeg-master-latest-win64-gpl-shared\bin"
AudioSegment.converter = r"D:\ffmpeg-master-latest-win64-gpl-shared\bin\ffmpeg.exe"
AudioSegment.ffmpeg = r"D:\ffmpeg-master-latest-win64-gpl-shared\bin\ffmpeg.exe"
AudioSegment.ffprobe = r"D:\ffmpeg-master-latest-win64-gpl-shared\bin\ffprobe.exe"
# Configurare pentru ImageMagick
IMAGEMAGICK_BINARY = r"d:\Program Files\ImageMagick-7.1.1-Q16-HDRI\magick.exe" # Ajustează calea conform instalării tale
change_settings({"IMAGEMAGICK_BINARY": IMAGEMAGICK_BINARY})
class VoiceConverter:
def __init__(self, api_key):
print("Inițializare client OpenAI...")
openai.api_key = api_key
def close_clips(self, *clips):
for clip in clips:
try:
if clip is not None:
clip.close()
except:
pass
def generate_speech_for_sentence(self, text, output_file, voice="alloy"):
"""Generează voce pentru o singură propoziție"""
try:
# Creează directorul 'voices' dacă nu există
os.makedirs('voices', exist_ok=True)
# Generează un nume de fișier bazat pe text
safe_filename = "".join(x for x in text[:30] if x.isalnum()) + ".mp3"
voice_path = os.path.join('voices', safe_filename)
# Verifică dacă fișierul există deja
if os.path.exists(voice_path):
print(f"Folosesc vocea existentă pentru: {text[:30]}...")
# Copiază fișierul existent în locația temporară
with open(voice_path, 'rb') as src, open(output_file, 'wb') as dst:
dst.write(src.read())
else:
print(f"Generez voce nouă pentru: {text[:30]}...")
response = openai.audio.speech.create(
model="tts-1",
voice=voice,
input=text
)
# Salvează în ambele locații
response.stream_to_file(voice_path)
with open(voice_path, 'rb') as src, open(output_file, 'wb') as dst:
dst.write(src.read())
return True
except Exception as e:
print(f"❌ Eroare la generarea vocii pentru propoziția: {text}")
print(f"Eroare: {str(e)}")
return False
def create_text_clip(self, text, duration, video_size):
"""Creează un TextClip cu formatare specifică"""
txt_clip = TextClip(text,
font='Arial',
fontsize=30,
color='white',
# bg_color='black', # aici daca vrei background la text
# stroke_color='black',
# stroke_width=2,
size=(video_size[0], None),
method='caption')
txt_clip = txt_clip.set_duration(duration)
# Poziționează textul în partea de jos a video-ului
txt_clip = txt_clip.set_position(('center', 'bottom'))
return txt_clip
def process_video(self, video_path, text, output_path, voice="alloy"):
print(f"\n=== Începe procesarea video ===")
video = None
final_audio = None
audio_clips = []
text_clips = []
temp_files = []
try:
if not os.path.exists(video_path):
print(f"❌ Fișierul video nu există: {video_path}")
return False
# Încarcă video-ul
print("\n1. Încărcăm video-ul...")
video = VideoFileClip(video_path)
video_size = video.size
video_duration = video.duration
print(f"Durata video: {video_duration} secunde")
# Împarte textul în propoziții și generează audio pentru fiecare
sentences = [s.strip() for s in text.split('.') if s.strip()]
sentence_audios = []
# Prima trecere: generează toate audio-urile și calculează durata totală
print("\n2. Generăm audio pentru fiecare propoziție...")
total_audio_duration = 0
for i, sentence in enumerate(sentences):
temp_file = tempfile.NamedTemporaryFile(suffix='.mp3', delete=False)
temp_files.append(temp_file.name)
temp_file.close()
if self.generate_speech_for_sentence(sentence + ".", temp_file.name, voice):
audio = AudioFileClip(temp_file.name)
sentence_audios.append((sentence, audio))
total_audio_duration += audio.duration
# Calculează timpul disponibil și pauzele necesare
available_time = video_duration - 5 # Rezervăm 5 secunde la final
total_pause_time = available_time - total_audio_duration
pauses_needed = len(sentences) - 1
if pauses_needed > 0:
pause_duration = total_pause_time / pauses_needed
print(f"\nTimpul total pentru pauze: {total_pause_time:.2f} secunde")
print(f"Durata fiecărei pauze: {pause_duration:.2f} secunde")
else:
pause_duration = 0
# A doua trecere: construiește audio-ul și textul sincronizat
print("\n3. Construim audio-ul și textul sincronizat...")
current_time = 0
for i, (sentence, audio) in enumerate(sentence_audios):
# Adaugă audio
audio_clips.append(audio)
# Creează și adaugă text sincronizat
txt_clip = self.create_text_clip(sentence, audio.duration, video_size)
txt_clip = txt_clip.set_start(current_time)
text_clips.append(txt_clip)
current_time += audio.duration
# Adaugă pauză după fiecare propoziție (exceptând ultima)
if i < len(sentence_audios) - 1:
silence = AudioClip(lambda t: 0, duration=pause_duration)
audio_clips.append(silence)
current_time += pause_duration
# Adaugă pauza finală de 5 secunde
final_silence = AudioClip(lambda t: 0, duration=5)
audio_clips.append(final_silence)
# Concatenează toate clipurile audio
print("\n4. Combinăm toate clipurile audio...")
final_audio = concatenate_audioclips(audio_clips)
# Verifică durata audio finală
print(f"\nDurata audio finală: {final_audio.duration:.2f} secunde")
print(f"Durata video: {video_duration:.2f} secunde")
# Creează video-ul final cu text
print("\n5. Creăm video-ul final cu text...")
final_video = CompositeVideoClip([video] + text_clips)
final_video = final_video.set_audio(final_audio)
print("\n6. Exportăm rezultatul...")
final_video.write_videofile(
output_path,
codec='libx264',
audio_codec='aac',
temp_audiofile='temp-audio.m4a',
remove_temp=True
)
print("\n7. Export finalizat cu succes!")
return True
except Exception as e:
print(f"❌ Eroare la procesarea video: {str(e)}")
return False
finally:
print("\n8. Curățăm resursele...")
self.close_clips(video, final_audio)
for clip in audio_clips:
self.close_clips(clip)
for clip in text_clips:
self.close_clips(clip)
time.sleep(1)
for temp_file in temp_files:
try:
if os.path.exists(temp_file):
os.unlink(temp_file)
except Exception as e:
print(f"⚠️ Nu am putut șterge fișierul temporar {temp_file}: {str(e)}")
def main():
OPENAI_API_KEY = "YOUR-API-KEY"
video_path = r"e:\De pus pe FTP 2\Cum se spala corect sosetele la mana, la chiuveta.mp4"
output_path = "video_cu_voce_si_text_sincronizat.mp4"
text = """
How to wash socks by hand, under the tap.
First, turn on the tap with warm water and wet both socks well, rinsing them thoroughly.
Then, take the soap and, using circular movements, start rubbing the socks.
It is important to cover all surfaces with soap.
After lathering the socks well, continue rubbing them so that the foam penetrates each fiber.
When the foam starts to turn black, it is a sign that the dirt is coming out of the fabric.
After about two minutes of rubbing, rinse the socks with warm water until the water runs clear.
Finally, wring the socks well and place them on the radiator to dry.
Now the socks are clean and ready to dry.
"""
print("\n=== Începe procesul complet ===")
converter = VoiceConverter(OPENAI_API_KEY)
success = converter.process_video(video_path, text, output_path)
if success:
print(f"\n✅ Procesare completă! Video-ul a fost salvat ca: {output_path}")
else:
print("\n❌ Procesarea a eșuat!")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment