Améliorations sous-titres et interface
This commit is contained in:
parent
8e36769112
commit
7e5547a515
1 changed files with 54 additions and 40 deletions
94
app.py
94
app.py
|
@ -79,7 +79,7 @@ class AudioLoader:
|
|||
audio, sr = librosa.load(file_path, sr=16000)
|
||||
return audio, sr
|
||||
|
||||
def burn_subtitles(video_path, srt_content):
|
||||
def burn_subtitles(video_path, srt_content, subtitle_style):
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix='.srt') as temp_srt:
|
||||
temp_srt.write(srt_content.encode('utf-8'))
|
||||
temp_srt_path = temp_srt.name
|
||||
|
@ -87,15 +87,15 @@ def burn_subtitles(video_path, srt_content):
|
|||
output_path = os.path.splitext(video_path)[0] + '_with_captions.mp4'
|
||||
temp_video_path = os.path.splitext(video_path)[0] + '_temp_video.mp4'
|
||||
temp_audio_path = os.path.splitext(video_path)[0] + '_temp_audio.aac'
|
||||
|
||||
|
||||
try:
|
||||
# Extract video metadata
|
||||
probe = ffmpeg.probe(video_path)
|
||||
video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
|
||||
|
||||
|
||||
if video_stream is None:
|
||||
raise ValueError("No video stream found in the input file.")
|
||||
|
||||
|
||||
width = int(video_stream['width'])
|
||||
height = int(video_stream['height'])
|
||||
|
||||
|
@ -103,24 +103,15 @@ def burn_subtitles(video_path, srt_content):
|
|||
ffmpeg.input(video_path).output(temp_audio_path, acodec='aac', audio_bitrate='128k').overwrite_output().run(capture_stdout=True, capture_stderr=True)
|
||||
|
||||
# Process video with subtitles (without audio)
|
||||
subtitle_style = (
|
||||
'Fontname=Arial,Fontsize=18,'
|
||||
'PrimaryColour=&HFFFFFF&,'
|
||||
'OutlineColour=&H000000&,'
|
||||
'BorderStyle=3,'
|
||||
'Outline=1,'
|
||||
'Shadow=1,'
|
||||
'MarginV=20'
|
||||
)
|
||||
ffmpeg.input(video_path).filter(
|
||||
'subtitles',
|
||||
temp_srt_path,
|
||||
'subtitles',
|
||||
temp_srt_path,
|
||||
force_style=subtitle_style
|
||||
).output(
|
||||
temp_video_path,
|
||||
vcodec='libx264',
|
||||
video_bitrate='2000k',
|
||||
an=None,
|
||||
temp_video_path,
|
||||
vcodec='libx264',
|
||||
video_bitrate='2000k',
|
||||
an=None,
|
||||
s=f'{width}x{height}'
|
||||
).overwrite_output().run(capture_stdout=True, capture_stderr=True)
|
||||
|
||||
|
@ -131,18 +122,18 @@ def burn_subtitles(video_path, srt_content):
|
|||
v=1,
|
||||
a=1
|
||||
).output(output_path, vcodec='libx264', acodec='aac').overwrite_output().run(capture_stdout=True, capture_stderr=True)
|
||||
|
||||
|
||||
# Check if the output file was created and has both video and audio streams
|
||||
if os.path.exists(output_path):
|
||||
output_probe = ffmpeg.probe(output_path)
|
||||
output_video_stream = next((stream for stream in output_probe['streams'] if stream['codec_type'] == 'video'), None)
|
||||
output_audio_stream = next((stream for stream in output_probe['streams'] if stream['codec_type'] == 'audio'), None)
|
||||
|
||||
|
||||
if output_video_stream is None or output_audio_stream is None:
|
||||
raise ValueError("Output file is missing video or audio stream.")
|
||||
else:
|
||||
raise FileNotFoundError("Output file was not created.")
|
||||
|
||||
|
||||
except (ffmpeg.Error, ValueError, FileNotFoundError) as e:
|
||||
st.error(f"An error occurred while burning subtitles: {str(e)}")
|
||||
return None
|
||||
|
@ -223,24 +214,47 @@ if uploaded_file is not None:
|
|||
if 'srt_content' in st.session_state:
|
||||
edited_srt = st.text_area("Edit Captions (SRT format)", st.session_state.srt_content, height=300)
|
||||
|
||||
if st.button("Burn Captions and Download"):
|
||||
with st.spinner("Burning captions onto video..."):
|
||||
output_path = burn_subtitles(st.session_state.temp_video_path, edited_srt)
|
||||
if st.button("Burn Captions and Download"):
|
||||
with st.spinner("Burning captions onto video..."):
|
||||
subtitle_style = (
|
||||
'Fontname=Arial,Fontsize=16,'
|
||||
'PrimaryColour=&H00FFFFFF&,'
|
||||
'SecondaryColour=&H00000000&,'
|
||||
'OutlineColour=&H00000000&,'
|
||||
'BackColour=&H40000000&,'
|
||||
'BorderStyle=1,'
|
||||
'Outline=1,'
|
||||
'Shadow=1,'
|
||||
'MarginV=20'
|
||||
)
|
||||
output_path = burn_subtitles(st.session_state.temp_video_path, edited_srt, subtitle_style)
|
||||
|
||||
if output_path:
|
||||
with open(output_path, "rb") as file:
|
||||
st.download_button(
|
||||
label="Download Video with Captions",
|
||||
data=file,
|
||||
file_name="video_with_captions.mp4",
|
||||
mime="video/mp4"
|
||||
)
|
||||
if output_path:
|
||||
with open(output_path, "rb") as file:
|
||||
st.download_button(
|
||||
label="Download Video with Captions",
|
||||
data=file,
|
||||
file_name="video_with_captions.mp4",
|
||||
mime="video/mp4"
|
||||
)
|
||||
|
||||
os.remove(output_path)
|
||||
os.remove(st.session_state.temp_audio_path) # Remove the temporary audio file
|
||||
if 'temp_audio_path' in st.session_state:
|
||||
del st.session_state.temp_audio_path # Remove the audio path from session state
|
||||
else:
|
||||
st.error("Failed to burn captions onto the video.")
|
||||
os.remove(output_path)
|
||||
os.remove(st.session_state.temp_audio_path)
|
||||
if 'temp_audio_path' in st.session_state:
|
||||
del st.session_state.temp_audio_path
|
||||
else:
|
||||
st.error("Failed to burn captions onto the video.")
|
||||
if st.button("Reset"):
|
||||
# Clear session state
|
||||
for key in list(st.session_state.keys()):
|
||||
del st.session_state[key]
|
||||
|
||||
os.remove(st.session_state.temp_video_path)
|
||||
# Remove temporary files
|
||||
if 'temp_video_path' in st.session_state and os.path.exists(st.session_state.temp_video_path):
|
||||
os.remove(st.session_state.temp_video_path)
|
||||
if 'web_compatible_video_path' in st.session_state and os.path.exists(st.session_state.web_compatible_video_path):
|
||||
os.remove(st.session_state.web_compatible_video_path)
|
||||
if 'temp_audio_path' in st.session_state and os.path.exists(st.session_state.temp_audio_path):
|
||||
os.remove(st.session_state.temp_audio_path)
|
||||
|
||||
st.success("All data has been reset. You can now upload a new video.")
|
||||
|
|
Loading…
Reference in a new issue