Forráskód Böngészése

voice messages: bridge Matrix voice messages to native Signal voice messages

Sumner Evans 3 éve
szülő
commit
b8c31df0d3

+ 8 - 4
mautrix_signal/portal.py

@@ -80,7 +80,7 @@ from .db import (
     Reaction as DBReaction,
 )
 from .formatter import matrix_to_signal, signal_to_matrix
-from .util import id_to_str, to_ogg
+from .util import id_to_str, to_m4a, to_ogg
 
 if TYPE_CHECKING:
     from .__main__ import SignalBridge
@@ -250,11 +250,15 @@ class Portal(DBPortal, BasePortal):
     # region Matrix event handling
 
     @staticmethod
-    def _make_attachment(message: MediaMessageEventContent, path: str) -> Attachment:
+    async def _make_attachment(message: MediaMessageEventContent, path: str) -> Attachment:
+        outgoing_filename = path
+        if message.msgtype == MessageType.AUDIO:
+            outgoing_filename = await to_m4a(path)
+            message.info.mimetype = "audio/mp4"
         attachment = Attachment(
             custom_filename=message.body,
             content_type=message.info.mimetype,
-            outgoing_filename=path,
+            outgoing_filename=outgoing_filename,
         )
         info = message.info
         attachment.width = info.get("w", info.get("width", 0))
@@ -345,7 +349,7 @@ class Portal(DBPortal, BasePortal):
             text, mentions = await matrix_to_signal(message)
         elif message.msgtype.is_media:
             attachment_path = await self._download_matrix_media(message)
-            attachment = self._make_attachment(message, attachment_path)
+            attachment = await self._make_attachment(message, attachment_path)
             attachments = [attachment]
             text = message.body if is_relay else None
             self.log.trace("Formed outgoing attachment %s", attachment)

+ 1 - 1
mautrix_signal/util/__init__.py

@@ -1,3 +1,3 @@
-from .audio_convert import to_ogg
+from .audio_convert import to_m4a, to_ogg
 from .color_log import ColorFormatter
 from .id_to_str import id_to_str

+ 23 - 0
mautrix_signal/util/audio_convert.py

@@ -15,6 +15,7 @@
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 from typing import Optional
+from pathlib import Path
 import asyncio
 import logging
 import mimetypes
@@ -58,3 +59,25 @@ async def to_ogg(data: bytes, mime: str) -> Optional[bytes]:
                 stderr.decode("utf-8") if stderr is not None else f"unknown ({proc.returncode})"
             )
             raise ChildProcessError(f"ffmpeg error: {err_text}")
+
+
+async def to_m4a(path_str: str) -> Optional[str]:
+    path = Path(path_str)
+    output_file_name = (path.parent / (path.stem + ".m4a")).absolute().as_posix()
+    proc = await asyncio.create_subprocess_exec(
+        "ffmpeg",
+        "-i",
+        path,
+        "-c:a",
+        "aac",
+        output_file_name,
+        stdout=asyncio.subprocess.PIPE,
+        stdin=asyncio.subprocess.PIPE,
+    )
+    _, stderr = await proc.communicate()
+    if proc.returncode == 0:
+        path.unlink(missing_ok=True)
+        return output_file_name
+    else:
+        err_text = stderr.decode("utf-8") if stderr is not None else f"unknown ({proc.returncode})"
+        raise ChildProcessError(f"ffmpeg error: {err_text}")