amigniter / mod_audio_stream

FreeSWITCH module to stream audio to websocket and receive response
MIT License
66 stars 31 forks source link

[accidental event] Websocket server can't receive metadata before audio streaming starts. #44

Open chinarui-na opened 2 months ago

chinarui-na commented 2 months ago

I want voice recognition on the called party in real time. I was called the Connect event again, initiating a two-way media bug. caller

uuid_audio_stream channelId_caller start ws://127.0.0.1:3001 mono 8k caller_number

callee

uuid_audio_stream channelId_callee start ws://127.0.0.1:3001 mono 8k callee_number

websocket receives two connections, but only once metadata, sometimes caller_number, sometimes callee_number, or caller and callee.

my websocket handler code

public class AudioStreamHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
    private static final String FILE_NAME = "received_data.raw";
    private WebSocketClient webSocketClient;
    private HashMap<ChannelId,WebSocketClient> webSocketClientHashMap = new HashMap<>();
    private HashMap<ChannelId,byte []> bytesMap = new HashMap<>();
    public String decodeUTF8(byte[] utf8Bytes) {
        if (utf8Bytes == null) {
            return null;
        }
        return new String(utf8Bytes, StandardCharsets.UTF_8);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {
        if (frame instanceof TextWebSocketFrame) {
            TextWebSocketFrame msgContent = (TextWebSocketFrame) frame;
            String content = msgContent.text();
            log.info("#### content {}",content);
            String name = decodeUTF8(msgContent.text().getBytes());
            log.info("#### name: " + name);
            WebSocketClient webSocketClient = new WebSocketClient(name);
            webSocketClientHashMap.put(ctx.channel().id(),webSocketClient);
        } else if (frame instanceof BinaryWebSocketFrame) {
            BinaryWebSocketFrame msg = (BinaryWebSocketFrame) frame;
            ByteBuf content = msg.content();
            byte[] byteArray = new byte[content.readableBytes()];
            content.readBytes(byteArray);
            if(webSocketClientHashMap.containsKey(ctx.channel().id())){
                webSocketClientHashMap.get(ctx.channel().id()).sendFile(byteArray);
            }
        } else {
        }
    }

    private void saveToFile(byte[] data) {
        try (FileOutputStream fos = new FileOutputStream(FILE_NAME, true)) {
            fos.write(data);
            System.out.println("Data appended to file: " + FILE_NAME);
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("Error saving data to file: " + e.getMessage());
        }
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        log.error("exception ", cause);
        Channel channel = ctx.channel();
        if(channel.isActive())ctx.close();
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        log.info("client,channel id" + ctx.channel().id());
    }

}
chinarui-na commented 1 month ago
image
chinarui-na commented 1 month ago

48b4f1bd20b09fdf3fc6a88716ea2c4a

chinarui-na commented 1 month ago
image
amigniter commented 1 month ago

Unfortunately we can't reproduce such an issue, working properly here. Each metadata for caller uuid and the callee is sent properly. Can you please tell me how to reproduce it and of course I will investigate it to see if there is a potential issue.

A potential issue here can be a change that you did before websocket start (printing info). It doesn't work like that, and can cause unpredictable behaviour. When you obtain a session using _switch_core_sessionlocate, the session is under a lock and you must unlock it when you're done with it.

amigniter commented 1 month ago
mm@desktop:~/wsServer$ ./server 
Waiting for incoming connections...

Connection opened, addr: 192.168.0.19
I receive a message: initial1 (8), from: 192.168.0.19, type:1
Connection opened, addr: 192.168.0.19
I receive a message: initial22 (9), from: 192.168.0.19, type:1
Connection closed, addr: 192.168.0.19
Connection closed, addr: 192.168.0.19

This a working example, initial1 was the initial message from the caller, and initial22 from the callee.

chinarui-na commented 1 month ago

I delete log. I started two audio streams in the answer event, one is caller and the other is callee, and they carry metadata. I found that m_initial_meta would be changed between the start of the websocket connection and the success of the connection, possibly because there was a problem with the source data. by the way, It's a question of probability.

amigniter commented 1 month ago

Thanks. I see. Ok, do some more tests please when you can. As I said, I can't reproduce it and it's working fine here. Can't see how it could possibly change. But, if it still happens for you for some reason, I will move it from the class and make it a member of private data of the channel, but first we'll need to find why it's being changed (i see on your pics char pointer points to some weird location).

chinarui-na commented 1 month ago

Okay, when I find out, I'll come back here.

2954456878 commented 1 month ago

Is there any new progress? I have the same problem. image Two different calls, different metadata, the same value is printed when sending initial metadata,metadata value is overwritten

2954456878 commented 1 month ago

image metadata value is truncated

SumyabazarBaatar commented 4 weeks ago

i have the same issue. its like a playing coin toss. sometimes i get, sometimes i cant get metadata that i send. if i receive, last parts are truncated sometimes. needs to be fixed.

chinarui-na commented 3 weeks ago

You can fix this problem by modifying the code

SumyabazarBaatar commented 3 weeks ago

i dont want to ruin the code. cuz im not good at c++. but in my view, there is like zero problems to send metadata wrong. but i got still strange metadata that i dont want to receive. Example :

2024-08-16 12:02:57.527718 93.83% [DEBUG] mod_audio_stream.c:150 mod_audio_stream cmd: 8e378083-3205-44f6-81e1-18e1de804cab start ws://Address/pub/audiostream mono 16k {"age":1,"type":"sometype","someID":"66becf604af36c1543b13ec8"}
2024-08-16 12:02:57.527718 93.83% [DEBUG] mod_audio_stream.c:81 calling stream_session_init.
2024-08-16 12:02:57.527718 93.83% [DEBUG] audio_streamer_glue.cpp:368 (8e378083-3205-44f6-81e1-18e1de804cab) resampling from 8000 to 16000
2024-08-16 12:02:57.527718 93.83% [DEBUG] audio_streamer_glue.cpp:379 (8e378083-3205-44f6-81e1-18e1de804cab) stream_data_init
2024-08-16 12:02:57.527718 93.83% [DEBUG] mod_audio_stream.c:87 adding bug.
2024-08-16 12:02:57.527718 93.83% [DEBUG] switch_core_media_bug.c:976 Attaching BUG to sofia/external/<PHONE NUMBER>@IPHost 
2024-08-16 12:02:57.527718 93.83% [DEBUG] mod_audio_stream.c:91 setting bug private data.
2024-08-16 12:02:57.527718 93.83% [DEBUG] mod_audio_stream.c:94 exiting start_capture.
2024-08-16 12:02:57.807709 93.83% [DEBUG] audio_streamer_glue.cpp:135 sending initial metadata sivep
2024-08-16 12:03:05.867727 93.70% [NOTICE] sofia.c:1065 Hangup sofia/external/><PHONE NUMBER>@IPHost [CS_EXECUTE] [NORMAL_CLEARING]

i cant find what kind of code makes my metadata to sivep. did you find out your problem ? if you do, Can u explain the problem to me?

2954456878 commented 1 week ago

您可以通过修改代码来解决这个问题

您可以通过修改代码来解决这个问题

Can you submit a PR?