Mentosyevsky commited on
Commit
c895669
·
verified ·
1 Parent(s): 5ceaa62

Upload 3 files

Browse files
Files changed (3) hide show
  1. audio.ipynb +56 -0
  2. text.py +153 -0
  3. video.ipynb +471 -0
audio.ipynb ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "46343fb7",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "import whisper\n",
11
+ "\n",
12
+ "# 加载 Whisper 模型\n",
13
+ "model = whisper.load_model(\"base\") # 可以选择不同大小的模型:base, small, medium, large\n",
14
+ "\n",
15
+ "\n",
16
+ "# 传入音频文件路径进行转录\n",
17
+ "audio_path = \"test_audio.mp3\" # 替换为你自己的音频文件路径\n",
18
+ "transcribed_text = model.transcribe(audio_path)\n",
19
+ "\n",
20
+ "\n",
21
+ "# 输出转录结果\n",
22
+ "print(\"转录文本:\")\n",
23
+ "print(transcribed_text[\"text\"])\n"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "code",
28
+ "execution_count": null,
29
+ "id": "e19c2bcf",
30
+ "metadata": {},
31
+ "outputs": [],
32
+ "source": []
33
+ }
34
+ ],
35
+ "metadata": {
36
+ "kernelspec": {
37
+ "display_name": "Python 3 (ipykernel)",
38
+ "language": "python",
39
+ "name": "python3"
40
+ },
41
+ "language_info": {
42
+ "codemirror_mode": {
43
+ "name": "ipython",
44
+ "version": 3
45
+ },
46
+ "file_extension": ".py",
47
+ "mimetype": "text/x-python",
48
+ "name": "python",
49
+ "nbconvert_exporter": "python",
50
+ "pygments_lexer": "ipython3",
51
+ "version": "3.11.5"
52
+ }
53
+ },
54
+ "nbformat": 4,
55
+ "nbformat_minor": 5
56
+ }
text.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ from langdetect import detect
4
+ import streamlit as st
5
+ import fitz # PyMuPDF
6
+ from docx import Document
7
+ from openai import OpenAI
8
+ import matplotlib.pyplot as plt
9
+ import seaborn as sns
10
+ import io
11
+ import re
12
+
13
+ # Load environment variables
14
+ load_dotenv()
15
+
16
+ # Initialize OpenAI client
17
+ client = OpenAI(api_key="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")
18
+
19
+ # Define multilingual prompts (for comprehension) + fixed English response instruction
20
+ PROMPTS = {
21
+ "en": """You are a media ethics analyst. Please evaluate the following text according to the criteria:
22
+ 1. Does it contain hate speech?
23
+ 2. Does it show racial or cultural discrimination?
24
+ 3. Does it spread misinformation?
25
+ 4. Does it contain stereotypes or misleading impressions?
26
+
27
+ Rate each item from 0 to 5 and explain briefly. Then provide an overall score out of 100 and a summary.
28
+ ⚠️ Please write the entire response in English.""",
29
+ "zh": """你是一位媒体伦理分析专家。请根据以下标准分析文本:
30
+ 1. 是否包含仇恨言论?
31
+ 2. 是否存在种族或文化歧视?
32
+ 3. 是否传播虚假信息?
33
+ 4. 是否有刻板印象或引导性误导?
34
+
35
+ 请每项打分(0~5)并说明理由。最后提供总评分(满分100)和简要结论。
36
+ ⚠️ Please write the entire response in English.""",
37
+ "es": """Eres un analista de ética mediática. Evalúa el texto con base en:
38
+ 1. ¿Contiene discurso de odio?
39
+ 2. ¿Muestra discriminación racial o cultural?
40
+ 3. ¿Difunde información falsa?
41
+ 4. ¿Incluye estereotipos o impresiones engañosas?
42
+
43
+ Califica del 0 al 5, explica brevemente cada punto y da un puntaje total de 100.
44
+ ⚠️ Please write the entire response in English.""",
45
+ "fr": """Vous êtes un analyste en éthique des médias. Veuillez évaluer ce texte :
46
+ 1. Contient-il un discours haineux ?
47
+ 2. Présente-t-il une discrimination raciale ou culturelle ?
48
+ 3. Diffuse-t-il de fausses informations ?
49
+ 4. Contient-il des stéréotypes ou impressions trompeuses ?
50
+
51
+ Attribuez une note de 0 à 5 pour chaque point, puis une note sur 100 et un résumé.
52
+ ⚠️ Please write the entire response in English.""",
53
+ "ru": """Вы — аналитик в области медиаэтики. Проанализируйте текст:
54
+ 1. Есть ли язык вражды?
55
+ 2. Есть ли расовая или культурная дискриминация?
56
+ 3. Содержит ли дезинформацию?
57
+ 4. Есть ли стереотипы или вводящие в заблуждение образы?
58
+
59
+ Оцените каждый пункт по шкале от 0 до 5. Итоговая оценка — из 100.
60
+ ⚠️ Please write the entire response in English.""",
61
+ "ar": """أنت محلل أخلاقيات إعلام. قيّم النص وفقًا لما يلي:
62
+ 1. هل يحتوي على خطاب كراهية؟
63
+ 2. هل يوجد تمييز عنصري أو ثقافي؟
64
+ 3. هل ينشر معلومات مضللة؟
65
+ 4. هل يتضمن صورًا نمطية أو انطباعات مضللة؟
66
+
67
+ قيّم من 0 إلى 5 لكل نقطة، وقدم التقييم النهائي من 100.
68
+ ⚠️ Please write the entire response in English."""
69
+ }
70
+
71
+ def extract_text(file):
72
+ if file.type == "application/pdf":
73
+ doc = fitz.open(stream=file.read(), filetype="pdf")
74
+ return "".join([page.get_text() for page in doc])
75
+ elif file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
76
+ doc = Document(file)
77
+ return "\n".join([para.text for para in doc.paragraphs])
78
+ return ""
79
+
80
+ def analyze_text(text, lang):
81
+ prompt = PROMPTS.get(lang, PROMPTS["en"])
82
+ response = client.chat.completions.create(
83
+ model="gpt-3.5-turbo-0125",
84
+ messages=[
85
+ {"role": "system", "content": prompt},
86
+ {"role": "user", "content": text}
87
+ ]
88
+ )
89
+ return response.choices[0].message.content
90
+
91
+ # Improved score extractor
92
+ def extract_scores(result_text):
93
+ lines = result_text.splitlines()
94
+ pattern = re.compile(r"(\d)\s*/\s*5")
95
+ scores = []
96
+
97
+ for line in lines:
98
+ match = pattern.search(line)
99
+ if match:
100
+ scores.append(int(match.group(1)))
101
+ if len(scores) == 4:
102
+ break
103
+
104
+ # Fill missing with 0s
105
+ while len(scores) < 4:
106
+ scores.append(0)
107
+
108
+ return scores
109
+
110
+ def draw_chart(scores):
111
+ criteria = ["Hate Speech", "Discrimination", "Misinformation", "Stereotyping"]
112
+ fig, ax = plt.subplots(figsize=(6, 4))
113
+ colors = sns.color_palette("Set2")
114
+ sns.barplot(x=criteria, y=scores, palette=colors, ax=ax)
115
+ ax.set_ylim(0, 5)
116
+ ax.set_ylabel("Score (0–5)")
117
+ ax.set_title("Content Harmfulness Evaluation")
118
+ plt.xticks(rotation=20)
119
+ buf = io.BytesIO()
120
+ plt.tight_layout()
121
+ plt.savefig(buf, format="png")
122
+ buf.seek(0)
123
+ return buf
124
+
125
+ # UI
126
+ st.set_page_config("Multilingual Harm Analyzer", "📄")
127
+ st.title("📄 Multilingual Harmful Content Analyzer")
128
+ st.markdown("Upload a **PDF** or **Word** file, or paste text to evaluate content harm based on media ethics principles.")
129
+
130
+ text_input = st.text_area("Or paste content here:", height=150)
131
+ uploaded_file = st.file_uploader("Upload PDF or Word file", type=["pdf", "docx"])
132
+
133
+ if st.button("🔍 Analyze Content"):
134
+ if not text_input.strip() and not uploaded_file:
135
+ st.error("Please paste some content or upload a document.")
136
+ else:
137
+ with st.spinner("Analyzing, please wait..."):
138
+ if uploaded_file:
139
+ text_input = extract_text(uploaded_file)
140
+
141
+ lang = detect(text_input)
142
+ result = analyze_text(text_input, lang)
143
+ scores = extract_scores(result)
144
+
145
+ st.success("Analysis complete ✅")
146
+ st.subheader("Results Summary")
147
+ st.markdown(result)
148
+ st.text(f"DEBUG: Extracted Scores: {scores}")
149
+
150
+ if all(s == 0 for s in scores):
151
+ st.warning("⚠️ Warning: No scores detected. The result format may have changed.")
152
+ else:
153
+ st.image(draw_chart(scores), caption="Evaluation Summary", use_column_width=True)
video.ipynb ADDED
@@ -0,0 +1,471 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "id": "2ea85ca1-e593-49b7-9071-53957f520e87",
7
+ "metadata": {},
8
+ "outputs": [
9
+ {
10
+ "name": "stdout",
11
+ "output_type": "stream",
12
+ "text": [
13
+ "Collecting openai-whisper\n",
14
+ " Downloading openai-whisper-20240930.tar.gz (800 kB)\n",
15
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m800.5/800.5 kB\u001b[0m \u001b[31m2.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
16
+ "\u001b[?25h Installing build dependencies ... \u001b[?25ldone\n",
17
+ "\u001b[?25h Getting requirements to build wheel ... \u001b[?25ldone\n",
18
+ "\u001b[?25h Preparing metadata (pyproject.toml) ... \u001b[?25ldone\n",
19
+ "\u001b[?25hRequirement already satisfied: numba in /opt/anaconda3/lib/python3.12/site-packages (from openai-whisper) (0.59.1)\n",
20
+ "Requirement already satisfied: numpy in /opt/anaconda3/lib/python3.12/site-packages (from openai-whisper) (1.26.4)\n",
21
+ "Collecting torch (from openai-whisper)\n",
22
+ " Downloading torch-2.6.0-cp312-none-macosx_11_0_arm64.whl.metadata (28 kB)\n",
23
+ "Requirement already satisfied: tqdm in /opt/anaconda3/lib/python3.12/site-packages (from openai-whisper) (4.66.4)\n",
24
+ "Requirement already satisfied: more-itertools in /opt/anaconda3/lib/python3.12/site-packages (from openai-whisper) (10.1.0)\n",
25
+ "Collecting tiktoken (from openai-whisper)\n",
26
+ " Downloading tiktoken-0.9.0-cp312-cp312-macosx_11_0_arm64.whl.metadata (6.7 kB)\n",
27
+ "Requirement already satisfied: llvmlite<0.43,>=0.42.0dev0 in /opt/anaconda3/lib/python3.12/site-packages (from numba->openai-whisper) (0.42.0)\n",
28
+ "Requirement already satisfied: regex>=2022.1.18 in /opt/anaconda3/lib/python3.12/site-packages (from tiktoken->openai-whisper) (2023.10.3)\n",
29
+ "Requirement already satisfied: requests>=2.26.0 in /opt/anaconda3/lib/python3.12/site-packages (from tiktoken->openai-whisper) (2.32.2)\n",
30
+ "Requirement already satisfied: filelock in /opt/anaconda3/lib/python3.12/site-packages (from torch->openai-whisper) (3.13.1)\n",
31
+ "Requirement already satisfied: typing-extensions>=4.10.0 in /opt/anaconda3/lib/python3.12/site-packages (from torch->openai-whisper) (4.11.0)\n",
32
+ "Requirement already satisfied: networkx in /opt/anaconda3/lib/python3.12/site-packages (from torch->openai-whisper) (3.2.1)\n",
33
+ "Requirement already satisfied: jinja2 in /opt/anaconda3/lib/python3.12/site-packages (from torch->openai-whisper) (3.1.4)\n",
34
+ "Requirement already satisfied: fsspec in /opt/anaconda3/lib/python3.12/site-packages (from torch->openai-whisper) (2024.3.1)\n",
35
+ "Requirement already satisfied: setuptools in /opt/anaconda3/lib/python3.12/site-packages (from torch->openai-whisper) (69.5.1)\n",
36
+ "Collecting sympy==1.13.1 (from torch->openai-whisper)\n",
37
+ " Downloading sympy-1.13.1-py3-none-any.whl.metadata (12 kB)\n",
38
+ "Requirement already satisfied: mpmath<1.4,>=1.1.0 in /opt/anaconda3/lib/python3.12/site-packages (from sympy==1.13.1->torch->openai-whisper) (1.3.0)\n",
39
+ "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/anaconda3/lib/python3.12/site-packages (from requests>=2.26.0->tiktoken->openai-whisper) (2.0.4)\n",
40
+ "Requirement already satisfied: idna<4,>=2.5 in /opt/anaconda3/lib/python3.12/site-packages (from requests>=2.26.0->tiktoken->openai-whisper) (3.7)\n",
41
+ "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/anaconda3/lib/python3.12/site-packages (from requests>=2.26.0->tiktoken->openai-whisper) (2.2.2)\n",
42
+ "Requirement already satisfied: certifi>=2017.4.17 in /opt/anaconda3/lib/python3.12/site-packages (from requests>=2.26.0->tiktoken->openai-whisper) (2024.8.30)\n",
43
+ "Requirement already satisfied: MarkupSafe>=2.0 in /opt/anaconda3/lib/python3.12/site-packages (from jinja2->torch->openai-whisper) (2.1.3)\n",
44
+ "Downloading tiktoken-0.9.0-cp312-cp312-macosx_11_0_arm64.whl (1.0 MB)\n",
45
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.0/1.0 MB\u001b[0m \u001b[31m337.2 kB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
46
+ "\u001b[?25hDownloading torch-2.6.0-cp312-none-macosx_11_0_arm64.whl (66.5 MB)\n",
47
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m66.5/66.5 MB\u001b[0m \u001b[31m1.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:02\u001b[0mm\n",
48
+ "\u001b[?25hDownloading sympy-1.13.1-py3-none-any.whl (6.2 MB)\n",
49
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.2/6.2 MB\u001b[0m \u001b[31m1.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n",
50
+ "\u001b[?25hBuilding wheels for collected packages: openai-whisper\n",
51
+ " Building wheel for openai-whisper (pyproject.toml) ... \u001b[?25ldone\n",
52
+ "\u001b[?25h Created wheel for openai-whisper: filename=openai_whisper-20240930-py3-none-any.whl size=803373 sha256=17b60153bbb321b60e9e767ba6ef7ff6626cfed599180241ef5dd6afdb9c6db9\n",
53
+ " Stored in directory: /Users/chuanliu/Library/Caches/pip/wheels/7c/f5/6f/92094c35416f9397abb86b23cfe72fb255a3013012f983136d\n",
54
+ "Successfully built openai-whisper\n",
55
+ "Installing collected packages: sympy, torch, tiktoken, openai-whisper\n",
56
+ " Attempting uninstall: sympy\n",
57
+ " Found existing installation: sympy 1.12\n",
58
+ " Uninstalling sympy-1.12:\n",
59
+ " Successfully uninstalled sympy-1.12\n",
60
+ "Successfully installed openai-whisper-20240930 sympy-1.13.1 tiktoken-0.9.0 torch-2.6.0\n",
61
+ "Note: you may need to restart the kernel to use updated packages.\n"
62
+ ]
63
+ }
64
+ ],
65
+ "source": [
66
+ "pip install -U openai-whisper"
67
+ ]
68
+ },
69
+ {
70
+ "cell_type": "code",
71
+ "execution_count": 29,
72
+ "id": "fbf6f89d-e095-4da8-b700-1f061d1303a2",
73
+ "metadata": {},
74
+ "outputs": [
75
+ {
76
+ "name": "stdout",
77
+ "output_type": "stream",
78
+ "text": [
79
+ "Requirement already satisfied: imageio-ffmpeg in /opt/anaconda3/lib/python3.12/site-packages (0.6.0)\n",
80
+ "Note: you may need to restart the kernel to use updated packages.\n"
81
+ ]
82
+ }
83
+ ],
84
+ "source": [
85
+ "pip install imageio-ffmpeg"
86
+ ]
87
+ },
88
+ {
89
+ "cell_type": "code",
90
+ "execution_count": 38,
91
+ "id": "78a80c84-a833-4a44-ab2a-a29bfdeb2fa2",
92
+ "metadata": {},
93
+ "outputs": [
94
+ {
95
+ "name": "stdout",
96
+ "output_type": "stream",
97
+ "text": [
98
+ "\n",
99
+ "🎙 正在转录音频文本...\n"
100
+ ]
101
+ },
102
+ {
103
+ "name": "stderr",
104
+ "output_type": "stream",
105
+ "text": [
106
+ "/opt/anaconda3/lib/python3.12/site-packages/whisper/transcribe.py:126: UserWarning: FP16 is not supported on CPU; using FP32 instead\n",
107
+ " warnings.warn(\"FP16 is not supported on CPU; using FP32 instead\")\n"
108
+ ]
109
+ },
110
+ {
111
+ "name": "stdout",
112
+ "output_type": "stream",
113
+ "text": [
114
+ "\n",
115
+ "🎯 YOLO检测到的图案类别:\n",
116
+ "✅ 检测到图案:nazi_symbol\n",
117
+ "\n",
118
+ "🔎 内容安全风险分析(每类满足可能性 ≥ LIKELY 的帧计数):\n",
119
+ "Adult : ✅ 低风险(0 帧)\n",
120
+ "Spoof : ⚠️ 中等风险(15 帧)\n",
121
+ "Medical : ✅ 低风险(1 帧)\n",
122
+ "Violence : ✅ 低风险(0 帧)\n",
123
+ "Racy : ✅ 低风险(0 帧)\n",
124
+ "\n",
125
+ "📝 视觉文字识别(OCR):\n",
126
+ "Heil beforehand HOLD When 9 Nazi CNA facts : THT FLO High TRY T WORLD\n",
127
+ "Source: Sina TRTWORLD\n",
128
+ "5\n",
129
+ "waved\n",
130
+ "students\n",
131
+ "Source: Chinatimes called WORLD\n",
132
+ "When reviewing the parade\n",
133
+ "beforehand, we failed to\n",
134
+ "closely consider the meaning\n",
135
+ "of the historical facts\"\n",
136
+ "Source: Sina TOWORLD deplorable Share RT WORLD\n",
137
+ "German and Israeli TRY WORLD\n",
138
+ "German and Israeli officials\n",
139
+ "called the rally deplorable Chinares A after TRTWORLD\n",
140
+ "$\n",
141
+ "氏\n",
142
+ "students\n",
143
+ "waved Nazi flags\n",
144
+ "Source: Chinatimes TRT HOLD\n",
145
+ "and shouted\n",
146
+ "66\n",
147
+ "g Heil\"\n",
148
+ "with\n",
149
+ "raised arms\n",
150
+ "Source: Facebook/ wave Facebook g THY WORLD\n",
151
+ "heel TRE WORLD\n",
152
+ "કરી નારા\n",
153
+ "Source: Sina TRTWORLD\n",
154
+ "The school's principal\n",
155
+ "has resigned and shouted WORLD\n",
156
+ "When reviewing the parade\n",
157
+ "beforehand, we failed to\n",
158
+ "closely consider\n",
159
+ "Source: Sina RT WORLD TRT O\n",
160
+ "and shouted\n",
161
+ "\"Sieg Heil\"\n",
162
+ "with\n",
163
+ "raised arms\n",
164
+ "Source: Facebook/ education TR WORLD\n",
165
+ "German and Israeli officials\n",
166
+ "called the rally deplorable TRT WORLD\n",
167
+ "at a Taiwanese\n",
168
+ "high school's\n",
169
+ "Christmas\n",
170
+ "costume\n",
171
+ "parade\n",
172
+ "Source: Facebook/* 6 TRTWORLD\n",
173
+ "$6\n",
174
+ "The school's principal\n",
175
+ "has resigned and\n",
176
+ "Source: CNA TRTWORLD\n",
177
+ "High School failed TRTWOP D\n",
178
+ "O to this TRTWORLD\n",
179
+ "This\n",
180
+ "Nazi-themed\n",
181
+ "performance\n",
182
+ "Source: Facebook/ costume TRTWORLD\n",
183
+ "German and Israeli officials\n",
184
+ "called the rally deplorable meaning TWORLD video T WORLD\n",
185
+ "at a Taiwanese\n",
186
+ "high school's\n",
187
+ "Christmas\n",
188
+ "costume\n",
189
+ "parade\n",
190
+ "Source: Facebook/* FLO TRTWORLD\n",
191
+ "Kuang Fu High School!\n",
192
+ "was under fire after\n",
193
+ "Source: Chinatimes TWORLD\n",
194
+ "Share this video THE 5556 WORLD\n",
195
+ "When reviewing the parade\n",
196
+ "beforehand, we failed to\n",
197
+ "closely consider the meaning\n",
198
+ "of the\n",
199
+ "Source: Sina TRTWOP is TRE TAY - ! Israeli TRTWORLD\n",
200
+ "Kuang Fu High School\n",
201
+ "was under fire after\n",
202
+ "Source: Chinatimes we raised TWORLD\n",
203
+ "35\n",
204
+ "The school issued the\n",
205
+ "following statement:\n",
206
+ "Source: Chinatimes students TRTWORLD\n",
207
+ "This\n",
208
+ "Nazi-themed\n",
209
+ "performance\n",
210
+ "is happening\n",
211
+ "Source: Facebook/** The RTWORLD has was D statement Jarael rally 窓 Chinatimes TRTWORLD\n",
212
+ "Jarael Christmas EPA WORL TRTWORLD\n",
213
+ "Source: Facebook/ STWORLD\n",
214
+ "German and Israeli officials\n",
215
+ "called the rally deplorable TRTWORLD\n",
216
+ "46\n",
217
+ "The school's principal\n",
218
+ "has resigned and\n",
219
+ "Source: CNA 66 TRTWORLD\n",
220
+ "Kuang Fu High School\n",
221
+ "was under fire after\n",
222
+ "Source: Chinatimes\n",
223
+ "55 / Kuang TRTWORLD કરી fire minister waved Fu School TRT • principal arms under S TRT\n",
224
+ "and shouted\n",
225
+ "\"Sieg Heil\"\n",
226
+ "with\n",
227
+ "raised arms\n",
228
+ "Source: Facebook/ heel TRTWORLD\n",
229
+ "Taiwan's\n",
230
+ "education minister\n",
231
+ "apologised after\n",
232
+ "Source: EPA WORLD\n",
233
+ "Source: Sina 16 TRTWORLD\n",
234
+ "students\n",
235
+ "waved Nazi flags\n",
236
+ "wave\n",
237
+ "Source: Chinatimes ** $ officials TRT WORL\n",
238
+ "Source: Sina TRTWORLD\n",
239
+ "Taiwan's\n",
240
+ "education minister\n",
241
+ "apologised after 氏 T \" and parade THE WORLD\n",
242
+ "at a Taiwanese\n",
243
+ "high school's\n",
244
+ "Christmas\n",
245
+ "costume\n",
246
+ "parade\n",
247
+ "Source: Facebook/ TR を WORLD\n",
248
+ "When reviewing the parade\n",
249
+ "beforehand, we failed to\n",
250
+ "Source: Sina and shouted\n",
251
+ "\"Sieg Heil\"\n",
252
+ "with\n",
253
+ "raised arms\n",
254
+ "Source: Facebook/ TRTWORLD\n",
255
+ "16\n",
256
+ "The school's principal\n",
257
+ "has resigned and\n",
258
+ "Source: CNA RTWORLD\n",
259
+ "This\n",
260
+ "Nazi-themed\n",
261
+ "performance\n",
262
+ "is happening\n",
263
+ "Source: Facebook/ 93 THY at school's TRTWORLD\n",
264
+ "瓜瓜\n",
265
+ "5556\n",
266
+ "The school issued the\n",
267
+ "following statement:\n",
268
+ "Source: Chinatimes Sina TRTWORLD\n",
269
+ "The school's principal\n",
270
+ "has resigned and\n",
271
+ "Source: CNA This 46 TIRT WORLD\n",
272
+ "A\n",
273
+ "Source: Chinatimes German 35 TRTWORLD\n",
274
+ "份\n",
275
+ "Kuang Fu High School\n",
276
+ "was under fire after\n",
277
+ "Source: Chinatimes STWORLD with TRTWORLD\n",
278
+ "Taiwan's\n",
279
+ "education minister\n",
280
+ "apologised after\n",
281
+ "Source. EPA following Sieg consider resigned historical TRTWORLD\n",
282
+ "Share this video performance 55 瓜瓜 a THT • apologised 份 . , WORLD\n",
283
+ "When reviewing the parade\n",
284
+ "beforehand, we failed to\n",
285
+ "closely consider the meaning\n",
286
+ "Source: Sina TRTWORLD\n",
287
+ "This\n",
288
+ "Source: Facebook/ closely * નારા 5 TRT WORLD TRTWORLD\n",
289
+ "窓を\n",
290
+ "93\n",
291
+ "The school's principal\n",
292
+ "has resigned and\n",
293
+ "Source: CNA TRTWORLD\n",
294
+ "German and Israeli officials\n",
295
+ "called the rally school issued reviewing TRT WORLD WORLD\n",
296
+ "The school issued the\n",
297
+ "following statement\n",
298
+ "9 WORLD\n",
299
+ "When reviewing the parade\n",
300
+ "beforehand, we\n",
301
+ "Source: Sina TRTWORLD\n",
302
+ "students\n",
303
+ "waved Nazi flags\n",
304
+ "Source: Chinatimes TRTWORLD\n",
305
+ "This\n",
306
+ "Nazi-themed\n",
307
+ "performance\n",
308
+ "is happening\n",
309
+ "Source: Facebook/ TOWORLD\n",
310
+ "German and Israeli officials\n",
311
+ "called the rally deplorable THE WORLD\n",
312
+ "at a Taiwanese\n",
313
+ "high school's\n",
314
+ "Christmas\n",
315
+ "costume\n",
316
+ "parade\n",
317
+ "Source: Facebook/* flags TRTWORLD\n",
318
+ "The school issued the\n",
319
+ "following statement:\n",
320
+ "Source: Chinatimes O themed WORLD\n",
321
+ "When\n",
322
+ "Source: Sina TIRT Source TRTWORLD\n",
323
+ "and shouted\n",
324
+ "\"Sieg Heil\"\n",
325
+ "with\n",
326
+ "raised arms\n",
327
+ "Source: Facebook/ high RT TAY WORLD\n",
328
+ "at a Taiwanese\n",
329
+ "high school's\n",
330
+ "Christmas\n",
331
+ "costume\n",
332
+ "parade\n",
333
+ "Source: Facebook/* of TRTWORLD\n",
334
+ "Source: Chinatimes the TRTWORLD\n",
335
+ "S\n",
336
+ "Kuang Fu High School\n",
337
+ "was under fire after\n",
338
+ "Source: Chinares happening Taiwan's WORLD\n",
339
+ "When reviewing the parade\n",
340
+ "Source: Sina Taiwanese\n",
341
+ "\n",
342
+ "🔊 Whisper语音识别结果:\n",
343
+ " © BF-WATCH TV 2021\n"
344
+ ]
345
+ }
346
+ ],
347
+ "source": [
348
+ "from ultralytics import YOLO\n",
349
+ "import cv2\n",
350
+ "import whisper\n",
351
+ "import requests\n",
352
+ "import base64\n",
353
+ "import json\n",
354
+ "\n",
355
+ "# === 配置 ===\n",
356
+ "VIDEO_PATH = \"nazi_video.mp4\"\n",
357
+ "YOLO_MODEL_PATH = \"trained_dataset/runs/detect/train/weights/best.pt\"\n",
358
+ "API_KEY = \"AIzaSyAnkq9c1ljUyiTnH_R0dNt_MBs7YlILMU0\"\n",
359
+ "VISION_API_URL = f\"https://vision.googleapis.com/v1/images:annotate?key={API_KEY}\"\n",
360
+ "LIKELIHOOD_MAPPING = {\"UNKNOWN\": 0, \"VERY_UNLIKELY\": 1, \"UNLIKELY\": 2, \"POSSIBLE\": 3, \"LIKELY\": 4, \"VERY_LIKELY\": 5}\n",
361
+ "\n",
362
+ "# === 初始化 ===\n",
363
+ "model = YOLO(YOLO_MODEL_PATH)\n",
364
+ "cap = cv2.VideoCapture(VIDEO_PATH)\n",
365
+ "whisper_model = whisper.load_model(\"large\")\n",
366
+ "\n",
367
+ "safe_search_results = {\"adult\": 0, \"spoof\": 0, \"medical\": 0, \"violence\": 0, \"racy\": 0}\n",
368
+ "detected_texts = set()\n",
369
+ "detected_labels = set()\n",
370
+ "total_frames = 0\n",
371
+ "\n",
372
+ "while cap.isOpened():\n",
373
+ " ret, frame = cap.read()\n",
374
+ " if not ret:\n",
375
+ " break\n",
376
+ " total_frames += 1\n",
377
+ "\n",
378
+ " # YOLO 检测\n",
379
+ " results = model.predict(source=frame, conf=0.2, save=False, verbose=False)\n",
380
+ " if len(results[0].boxes) > 0:\n",
381
+ " for c in results[0].boxes.cls:\n",
382
+ " class_id = int(c.item())\n",
383
+ " class_name = results[0].names[class_id]\n",
384
+ " detected_labels.add(class_name)\n",
385
+ "\n",
386
+ " # 每 10 帧 Google 内容分析\n",
387
+ " if total_frames % 10 == 0:\n",
388
+ " _, buffer = cv2.imencode('.jpg', frame)\n",
389
+ " img_base64 = base64.b64encode(buffer).decode()\n",
390
+ " payload = {\n",
391
+ " \"requests\": [{\n",
392
+ " \"image\": {\"content\": img_base64},\n",
393
+ " \"features\": [\n",
394
+ " {\"type\": \"SAFE_SEARCH_DETECTION\"},\n",
395
+ " {\"type\": \"TEXT_DETECTION\"}\n",
396
+ " ]\n",
397
+ " }]\n",
398
+ " }\n",
399
+ " response = requests.post(VISION_API_URL, json=payload)\n",
400
+ " result = response.json()\n",
401
+ "\n",
402
+ " if \"responses\" in result and len(result[\"responses\"]) > 0:\n",
403
+ " safe = result[\"responses\"][0].get(\"safeSearchAnnotation\", {})\n",
404
+ " for key in safe_search_results.keys():\n",
405
+ " if LIKELIHOOD_MAPPING.get(safe.get(key, \"UNKNOWN\"), 0) >= 4:\n",
406
+ " safe_search_results[key] += 1\n",
407
+ "\n",
408
+ " texts = result[\"responses\"][0].get(\"textAnnotations\", [])\n",
409
+ " for text in texts:\n",
410
+ " detected_texts.add(text[\"description\"])\n",
411
+ "\n",
412
+ "cap.release()\n",
413
+ "\n",
414
+ "# === Whisper 音频转文字 ===\n",
415
+ "print(\"\\n🎙 正在转录音频文本...\")\n",
416
+ "whisper_result = whisper_model.transcribe(VIDEO_PATH)\n",
417
+ "\n",
418
+ "# === 输出结果 ===\n",
419
+ "print(\"\\n🎯 YOLO检测到的图案类别:\")\n",
420
+ "print(\"✅ 检测到图案:\" + \"、\".join(detected_labels) if detected_labels else \"❌ 未检测到任何图案\")\n",
421
+ "\n",
422
+ "def risk_level(count, total):\n",
423
+ " if count > total * 0.05:\n",
424
+ " return \"⛔️ 高风险\"\n",
425
+ " elif count > 5:\n",
426
+ " return \"⚠️ 中等风险\"\n",
427
+ " else:\n",
428
+ " return \"✅ 低风险\"\n",
429
+ "\n",
430
+ "print(\"\\n🔎 内容安全风险分析(每类满足可能性 ≥ LIKELY 的帧计数):\")\n",
431
+ "for k, v in safe_search_results.items():\n",
432
+ " print(f\"{k.capitalize():<10}: {risk_level(v, total_frames)}({v} 帧)\")\n",
433
+ "\n",
434
+ "print(\"\\n📝 视觉文字识别(OCR):\")\n",
435
+ "print(\" \".join(detected_texts) if detected_texts else \"无可识别文字\")\n",
436
+ "\n",
437
+ "print(\"\\n🔊 Whisper语音识别结果:\")\n",
438
+ "print(whisper_result[\"text\"] if whisper_result[\"text\"] else \"无有效语音\")\n"
439
+ ]
440
+ },
441
+ {
442
+ "cell_type": "code",
443
+ "execution_count": null,
444
+ "id": "0af3bf6e-01a0-4bda-8761-3f273060d7a6",
445
+ "metadata": {},
446
+ "outputs": [],
447
+ "source": []
448
+ }
449
+ ],
450
+ "metadata": {
451
+ "kernelspec": {
452
+ "display_name": "Python 3 (ipykernel)",
453
+ "language": "python",
454
+ "name": "python3"
455
+ },
456
+ "language_info": {
457
+ "codemirror_mode": {
458
+ "name": "ipython",
459
+ "version": 3
460
+ },
461
+ "file_extension": ".py",
462
+ "mimetype": "text/x-python",
463
+ "name": "python",
464
+ "nbconvert_exporter": "python",
465
+ "pygments_lexer": "ipython3",
466
+ "version": "3.12.4"
467
+ }
468
+ },
469
+ "nbformat": 4,
470
+ "nbformat_minor": 5
471
+ }