Help me fix the error please!

Hello, I have a project about processing and using a telegram bot to notify, but when I want to view the camera in real time (livecam) and process that command via the telegram bot, it still responds but the link it provides connection refused or "Not found: /stream" message when I click on that link, and on the serial it shows an error "E (828) httpd: httpd_server_init: error in listen (112)", I also don't know right how to fix it because I tried every port (except port 80 because I used it for image processing and then sent it via telegram), please help me fix this, I really appreciate it!!!, here are my 2 codes:
code esp32:

#include <WebServer.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include "esp_camera.h"
#include "esp_http_server.h"

const char* WIFI_SSID = "CA HA";
const char* WIFI_PASS = "khongmuoncho";
String BOTtoken = "8066448351:AAHGjtfdoWEfD2C93OD-zrcN-ZtUasEscGk";
String CHAT_ID = "7638387914";

#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"

WiFiClientSecure clientTCP;
UniversalTelegramBot bot(BOTtoken, clientTCP);
WebServer server(3000);

#define FLASH_LED_PIN 4
bool flashState = LOW;
bool liveStreamActive = false;
httpd_handle_t stream_httpd = NULL;

void configInitCamera() {
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    config.pin_d1 = Y3_GPIO_NUM;
    config.pin_d2 = Y4_GPIO_NUM;
    config.pin_d3 = Y5_GPIO_NUM;
    config.pin_d4 = Y6_GPIO_NUM;
    config.pin_d5 = Y7_GPIO_NUM;
    config.pin_d6 = Y8_GPIO_NUM;
    config.pin_d7 = Y9_GPIO_NUM;
    config.pin_xclk = XCLK_GPIO_NUM;
    config.pin_pclk = PCLK_GPIO_NUM;
    config.pin_vsync = VSYNC_GPIO_NUM;
    config.pin_href = HREF_GPIO_NUM;
    config.pin_sccb_sda = SIOD_GPIO_NUM;
    config.pin_sccb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG;
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;

    if (esp_camera_init(&config) != ESP_OK) {
        Serial.println("Camera init failed");
        return;
    }
}

void startCameraServer() {
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.server_port = 3000;
    httpd_uri_t stream_uri = {
        .uri = "/stream",
        .method = HTTP_GET,
        .handler = [](httpd_req_t *req) -> esp_err_t {
            camera_fb_t *fb = NULL;
            esp_err_t res = ESP_OK;
            res = httpd_resp_set_type(req, "multipart/x-mixed-replace; boundary=frame");

            while (liveStreamActive) {
                fb = esp_camera_fb_get();
                if (!fb) {
                    Serial.println("Camera capture failed");
                    res = ESP_FAIL;
                    break;
                } else {
                    httpd_resp_send_chunk(req, (const char*)fb->buf, fb->len);
                    esp_camera_fb_return(fb);
                }
            }
            return res;
        },
        .user_ctx = NULL
    };

    if (httpd_start(&stream_httpd, &config) == ESP_OK) {
        httpd_register_uri_handler(stream_httpd, &stream_uri);
    }
}

void stopCameraServer() {
    if (stream_httpd) {
        httpd_stop(stream_httpd);
        stream_httpd = NULL;
        Serial.println("Live stream server stopped");
    }
}

void sendPhotoTelegram(String detectedObject) {
    const char* myDomain = "api.telegram.org";
    camera_fb_t *fb = esp_camera_fb_get();
    if (!fb) {
        Serial.println("Camera capture failed");
        return;
    }

    if (clientTCP.connect(myDomain, 443)) {
        String head = "--boundary\r\nContent-Disposition: form-data; name=\"chat_id\"; \r\n\r\n" + CHAT_ID + "\r\n--boundary\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
        String tail = "\r\n--boundary--\r\n";

        clientTCP.println("POST /bot" + BOTtoken + "/sendPhoto HTTP/1.1");
        clientTCP.println("Host: " + String(myDomain));
        clientTCP.println("Content-Length: " + String(fb->len + head.length() + tail.length()));
        clientTCP.println("Content-Type: multipart/form-data; boundary=boundary");
        clientTCP.println();
        clientTCP.print(head);
        clientTCP.write(fb->buf, fb->len);
        clientTCP.print(tail);

        String msg = "Detected " + detectedObject + " in the area!";
        bot.sendMessage(CHAT_ID, msg, "");

        esp_camera_fb_return(fb);
        clientTCP.stop();
    }
}

void handleTelegramCommands(int numNewMessages) {
  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    if (chat_id != CHAT_ID){
      bot.sendMessage(chat_id, "Unauthorized user", "");
      continue;
    }

    String text = bot.messages[i].text;
    Serial.println(text);
    String from_name = bot.messages[i].from_name;
    if (text == "/adminmode") {
      String welcome = "Welcome, " + from_name + "\n";
      welcome += " <CHẾ ĐỘ CHO QUẢN TRỊ VIÊN>, Xin chào: ADMIN! \n";
      welcome += "/flash : Bật đèn LED \n";
      welcome += "/livecam : xem cam ở chế độ thời gian thực \n";
      bot.sendMessage(CHAT_ID, welcome, "");
    }
    if (text == "/livecam") {
      if (!liveStreamActive) {
        liveStreamActive = true;
        bot.sendMessage(chat_id, "View live stream at: http://" + WiFi.localIP().toString() + "/stream", "");
      } else {
        liveStreamActive = false;
        bot.sendMessage(chat_id, "Live stream stopped. Resuming object detection.", "");
      }
    }
    if (text == "/flash") {
      flashState = !flashState;
      digitalWrite(FLASH_LED_PIN, flashState);
      Serial.println("Flash state toggled");
    }
  }
}

void detectObject() {
    if (liveStreamActive) return;  // Bỏ qua phát hiện khi live stream đang bật

    camera_fb_t *fb = esp_camera_fb_get();
    if (!fb) {
        Serial.println("Camera capture failed");
        return;
    }

    const char* serverUrl = "http://192.168.1.11:80/detect_objects";
    HTTPClient http;
    http.begin(serverUrl);
    http.addHeader("Content-Type", "image/jpeg");

    int httpResponseCode = http.POST(fb->buf, fb->len);
    if (httpResponseCode > 0) {
        String response = http.getString();
        Serial.println(response);

        DynamicJsonDocument doc(1024);
        deserializeJson(doc, response);
        if (doc.containsKey("object")) {
            String detectedObject = doc["object"].as<String>();
            sendPhotoTelegram(detectedObject);
        }
    } else {
        Serial.println("Error on HTTP request");
    }

    esp_camera_fb_return(fb);
    http.end();
}

void setup() {
    Serial.begin(115200);
    pinMode(FLASH_LED_PIN, OUTPUT);
    digitalWrite(FLASH_LED_PIN, flashState);
    WiFi.begin(WIFI_SSID, WIFI_PASS);
    clientTCP.setCACert(TELEGRAM_CERTIFICATE_ROOT);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi");

    configInitCamera();
    
    server.begin();
    startCameraServer();
}

void loop() {
    static unsigned long lastDetectTime = 0;
    static unsigned long lastMessageCheckTime = 0;
    unsigned long currentMillis = millis();
    server.handleClient();
    if (!liveStreamActive && (currentMillis - lastDetectTime >= 200)) {
        detectObject();
        lastDetectTime = currentMillis;
    }
    
    if (currentMillis - lastMessageCheckTime >= 100) {
        int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
        if (numNewMessages > 0) {
            handleTelegramCommands(numNewMessages);
        }
        lastMessageCheckTime = currentMillis;
    }
}

serverpython code:

import requests
from flask import Flask, request, jsonify
import cv2
import numpy as np
import os

app = Flask(__name__)

net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")

with open("coco.names", "r") as f:
    classes = [line.strip() for line in f.readlines()]

layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers().flatten()]

target_labels = ["knife", "scissors", "cell phone", "baseball bat"]

TELEGRAM_TOKEN = "8066448351:AAHGjtfdoWEfD2C93OD-zrcN-ZtUasEscGk"
CHAT_ID = "7638387914"

def send_telegram_notification(detected_objects, img):
    url = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendPhoto"
    
    message = "Phat hien vat the:\n" + "\n".join([f"{obj['label']} (voi do chinh xac: {obj['confidence']:.2f})" for obj in detected_objects])
    
    temp_image_path = "detected_image.jpg"
    cv2.imwrite(temp_image_path, img)
    
    with open(temp_image_path, "rb") as image_file:
        data = {
            "chat_id": CHAT_ID,
            "caption": message
        }
        files = {
            "photo": image_file
        }
        response = requests.post(url, data=data, files=files)
    
    if response.status_code == 200:
        print("Notification sent successfully.")
    else:
        print("Failed to send notification:", response.text)

@app.route('/detect_objects', methods=['POST'])
def detect_objects():
    if request.method == 'POST':
        file = request.data
        np_array = np.frombuffer(file, np.uint8)
        img = cv2.imdecode(np_array, cv2.IMREAD_COLOR)

        if img is None:
            return jsonify({"error": "Could not decode the image."}), 400

        height, width = img.shape[:2]
        
        blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
        net.setInput(blob)
        outs = net.forward(output_layers)

        class_ids = []
        confidences = []
        boxes = []

        for out in outs:
            for detection in out:
                scores = detection[5:]
                class_id = np.argmax(scores)
                confidence = scores[class_id]
                
                label = classes[class_id]
                if confidence > 0.5 and label in target_labels:
                    center_x = int(detection[0] * width)
                    center_y = int(detection[1] * height)
                    w = int(detection[2] * width)
                    h = int(detection[3] * height)
                    x = int(center_x - w / 2)
                    y = int(center_y - h / 2)

                    boxes.append([x, y, w, h])
                    confidences.append(float(confidence))
                    class_ids.append(class_id)

        indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)

        detected_objects = []
        if len(indexes) > 0:
            for i in indexes.flatten():
                x, y, w, h = boxes[i]
                label = classes[class_ids[i]]
                detected_objects.append({"label": label, "confidence": confidences[i], "box": [x, y, w, h]})
                cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 255), 2)
                cv2.putText(img, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

        if detected_objects:
            send_telegram_notification(detected_objects, img)

        return jsonify({"detected_objects": detected_objects})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)