File size: 5,031 Bytes
a085f2e
 
 
 
 
 
 
 
 
 
 
 
 
5de0e95
 
 
a085f2e
 
 
5de0e95
a085f2e
 
5de0e95
 
a085f2e
 
5de0e95
 
 
 
 
a085f2e
5de0e95
 
 
 
a085f2e
5de0e95
 
a085f2e
 
5de0e95
 
 
 
 
 
 
 
 
 
a085f2e
5de0e95
 
a085f2e
 
5de0e95
 
 
 
 
 
 
 
 
 
a085f2e
5de0e95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a085f2e
5de0e95
 
a085f2e
 
 
 
 
5de0e95
 
 
 
a085f2e
5de0e95
a085f2e
 
5de0e95
a085f2e
5de0e95
 
 
 
 
 
 
a085f2e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#coding: utf-8
from pydub import AudioSegment
#from openai import OpenAI
#from io import BytesIO
#from typing import Any
#from typing import Dict
#from typing import IO
from typing import List
from typing import Optional
from typing import Tuple
from typing import Union
import base64
import io
import tempfile
import os
import streamlit as st

def concatenate_audio_files(audio_list: List[Tuple[Union[bytes, str], float]]) -> Optional[bytes]:
    """
    Concatène une liste de fichiers audio avec des effets sonores.

    Args:
        audio_list (List[Tuple[Union[bytes, str], float]]): Liste de tuples contenant les données audio
            (en bytes ou base64) et leur durée.

    Returns:
        Optional[bytes]: Données audio concaténées ou None en cas d'erreur.

    Raises:
        ValueError: Si la liste d'audio est vide ou invalide.
        IOError: Si une erreur se produit lors de la lecture/écriture des fichiers.
    """
    if not audio_list:
        st.error("Erreur : Aucun fichier audio à concaténer")
        return None

    final_audio = AudioSegment.empty()
    temp_files = []  # Pour le nettoyage des fichiers temporaires

    try:
        # Charger les effets sonores
        try:
            begin_sound = AudioSegment.from_mp3(
                "sound-effects/voice-message-play-begin/voice-message-play-begin-1.mp3"
            )
            end_sound = AudioSegment.from_mp3(
                "sound-effects/voice-message-play-ending/voice-message-play-ending-1.mp3"
            )
        except IOError as e:
            st.warning("Impossible de charger les effets sonores, continuation sans effets")
            begin_sound = end_sound = AudioSegment.empty()
        
        # 1.5 secondes de silence
        silence = AudioSegment.silent(duration=1500)
        
        for audio_data, _ in audio_list:
            try:
                # Convertir en bytes si c'est une chaîne base64
                if isinstance(audio_data, str):
                    try:
                        audio_bytes = base64.b64decode(audio_data)
                    except Exception as e:
                        st.error(f"Erreur de décodage base64 : {e}")
                        continue
                else:
                    audio_bytes = audio_data

                # Créer un fichier temporaire pour l'audio
                temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.mp3')
                temp_files.append(temp_file.name)
                temp_file.write(audio_bytes)
                temp_file.close()

                # Convertir les octets en un segment audio
                segment = AudioSegment.from_mp3(temp_file.name)
                
                # Ajouter le son de début, le segment TTS, le son de fin et le silence
                final_audio += begin_sound + segment + end_sound + silence
                
            except Exception as e:
                st.warning(f"Erreur lors du traitement d'un segment audio : {e}")
                continue
        
        if len(final_audio) == 0:
            raise ValueError("Aucun segment audio n'a pu être traité correctement")
        
        # Convertir le segment audio final en octets
        buffer = io.BytesIO()
        final_audio.export(buffer, format="mp3")
        return buffer.getvalue()

    except ValueError as e:
        st.error(f"Erreur de validation : {e}")
        return None
    except IOError as e:
        st.error(f"Erreur lors de la lecture ou de l'écriture des fichiers audio : {e}")
        return None
    except Exception as e:
        st.error(f"Une erreur inattendue s'est produite : {e}")
        return None
    finally:
        # Nettoyage des fichiers temporaires
        for temp_file in temp_files:
            try:
                os.remove(temp_file)
            except Exception:
                pass


def split_audio(audio_file, max_size_mb: int = 25) -> List[bytes]:
    """
    Divise un fichier audio en segments de taille maximale spécifiée.

    Args:
        audio_file: Fichier audio ouvert en mode binaire.
        max_size_mb (int): Taille maximale de chaque segment en Mo.

    Returns:
        List[bytes]: Liste des segments audio divisés sous forme de bytes.
    """
    try:
        audio_file.seek(0)
        audio = AudioSegment.from_file(audio_file)
        duration_ms = len(audio)
        segment_duration_ms = int(
            (max_size_mb * 1024 * 1024 * 8) /
            (audio.frame_rate * audio.sample_width * audio.channels)
        )

        segments = []
        for start in range(0, duration_ms, segment_duration_ms):
            end = min(start + segment_duration_ms, duration_ms)
            segment = audio[start:end]
            
            with io.BytesIO() as buffer:
                segment.export(buffer, format="mp3")
                segments.append(buffer.getvalue())

        return segments
    except Exception as e:
        print(f"Une erreur s'est produite lors de la division de l'audio : {e}")
        return []