feat: Phase 2.6 edges migration to Qdrant (TKG-only architecture)
Phase 2.6.1: co_occurrence_edges migration - build_co_occurrence_edges_from_qdrant() - Qdrant embeddings → frame grouping → YOLO objects - Result: 6679 edges (vs 6701 PostgreSQL) Phase 2.6.2: face_face_edges migration - build_face_face_edges_from_qdrant() - Qdrant embeddings → frame grouping → face pairs - mutual_gaze detection preserved - Result: 6 edges (exact match) Phase 2.6.3: speaker_face_edges migration - build_speaker_face_edges_from_qdrant() - Qdrant embeddings → trace_id frame ranges - SPEAKS_AS edge creation Architecture: - All edges use Qdrant payload (no face_detections queries) - PostgreSQL fallback for empty Qdrant - Estimated 3.6x performance improvement Testing: - Playground (3003): ✓ All Phase 2.6 logs verified - Edge counts: ✓ Close match with PostgreSQL - Fallback: ✓ Working Docs: - docs_v1.0/DESIGN/TKG_PHASE2_6_EDGES_MIGRATION.md - docs_v1.0/M4_workspace/2026-06-21_phase2_6_test.md
This commit is contained in:
1
scripts/add_yolo_to_chunks_v1.11.py
Symbolic link
1
scripts/add_yolo_to_chunks_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/add_yolo_to_chunks_v1.11.py
|
||||
1
scripts/age_benchmark_v1.11.py
Symbolic link
1
scripts/age_benchmark_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/age_benchmark_v1.11.py
|
||||
1
scripts/analyze_asr_lip_v1.11.py
Symbolic link
1
scripts/analyze_asr_lip_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/analyze_asr_lip_v1.11.py
|
||||
1
scripts/analyze_video_faces_v1.11.py
Symbolic link
1
scripts/analyze_video_faces_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/analyze_video_faces_v1.11.py
|
||||
157
scripts/appearance_processor.py
Normal file
157
scripts/appearance_processor.py
Normal file
@@ -0,0 +1,157 @@
|
||||
#!/opt/homebrew/bin/python3.11
|
||||
"""
|
||||
Appearance Processor - HSV color feature extraction for person tracking
|
||||
|
||||
Input:
|
||||
- video_path: source video
|
||||
- pose_json: pose.json with frame bboxes
|
||||
- output_path: output JSON
|
||||
|
||||
Output: appearance.json with HSV histogram per person per frame
|
||||
|
||||
Depends on pose.json (bbox). Same 0-based frame numbering as face/pose/mediapipe.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import argparse
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
|
||||
def extract_appearance(frame, bbox):
|
||||
x, y, w, h = bbox["x"], bbox["y"], bbox["width"], bbox["height"]
|
||||
if w <= 0 or h <= 0:
|
||||
return None
|
||||
|
||||
x1, y1 = max(0, x), max(0, y)
|
||||
x2 = min(frame.shape[1], x + w)
|
||||
y2 = min(frame.shape[0], y + h)
|
||||
if x2 <= x1 or y2 <= y1:
|
||||
return None
|
||||
|
||||
person_roi = frame[y1:y2, x1:x2]
|
||||
hsv = cv2.cvtColor(person_roi, cv2.COLOR_BGR2HSV)
|
||||
pixels = hsv.reshape(-1, 3).astype(np.float32)
|
||||
|
||||
# HSV histograms
|
||||
h_hist = cv2.calcHist([hsv], [0], None, [30], [0, 180]).flatten()
|
||||
s_hist = cv2.calcHist([hsv], [1], None, [32], [0, 256]).flatten()
|
||||
v_hist = cv2.calcHist([hsv], [2], None, [32], [0, 256]).flatten()
|
||||
h_sum = h_hist.sum() or 1
|
||||
s_sum = s_hist.sum() or 1
|
||||
v_sum = v_hist.sum() or 1
|
||||
|
||||
# Dominant colors via k-means
|
||||
dominant = []
|
||||
if len(pixels) >= 5:
|
||||
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
|
||||
_, labels, centers = cv2.kmeans(
|
||||
pixels, 5, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS
|
||||
)
|
||||
counts = np.bincount(labels.flatten())
|
||||
dominant = centers[np.argsort(-counts)[:5]].tolist()
|
||||
elif len(pixels) > 0:
|
||||
dominant = [pixels.mean(axis=0).tolist()]
|
||||
|
||||
# Upper / lower body split
|
||||
mid_y = y1 + (y2 - y1) // 2
|
||||
|
||||
def roi_hist(roi):
|
||||
if roi is None or roi.size == 0:
|
||||
return None
|
||||
hsv_r = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
|
||||
hh = cv2.calcHist([hsv_r], [0], None, [30], [0, 180]).flatten()
|
||||
sh = cv2.calcHist([hsv_r], [1], None, [32], [0, 256]).flatten()
|
||||
vh = cv2.calcHist([hsv_r], [2], None, [32], [0, 256]).flatten()
|
||||
hs = hh.sum() or 1
|
||||
ss = sh.sum() or 1
|
||||
vs = vh.sum() or 1
|
||||
return [(hh / hs).tolist(), (sh / ss).tolist(), (vh / vs).tolist()]
|
||||
|
||||
upper_roi = frame[y1:mid_y, x1:x2] if mid_y > y1 else None
|
||||
lower_roi = frame[mid_y:y2, x1:x2] if y2 > mid_y else None
|
||||
|
||||
return {
|
||||
"hsv_histogram": [
|
||||
(h_hist / h_sum).tolist(),
|
||||
(s_hist / s_sum).tolist(),
|
||||
(v_hist / v_sum).tolist(),
|
||||
],
|
||||
"dominant_colors": dominant,
|
||||
"upper_body": roi_hist(upper_roi),
|
||||
"lower_body": roi_hist(lower_roi),
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Appearance Processor")
|
||||
parser.add_argument("video_path", help="Video file path")
|
||||
parser.add_argument("pose_json", help="Pose JSON path (bbox input)")
|
||||
parser.add_argument("output_path", help="Output JSON path")
|
||||
parser.add_argument("--uuid", "-u", default="")
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.pose_json) as f:
|
||||
pose_data = json.load(f)
|
||||
|
||||
fps = pose_data.get("fps", 30.0)
|
||||
|
||||
cap = cv2.VideoCapture(args.video_path)
|
||||
if not cap.isOpened():
|
||||
print("[APPEARANCE] Cannot open video", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
frames_out = []
|
||||
for pose_frame in pose_data.get("frames", []):
|
||||
frame_num = pose_frame["frame"]
|
||||
persons = pose_frame.get("persons", [])
|
||||
if not persons:
|
||||
continue
|
||||
|
||||
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_num)
|
||||
ret, frame = cap.read()
|
||||
if not ret:
|
||||
continue
|
||||
|
||||
frame_persons = []
|
||||
for pid, person in enumerate(persons):
|
||||
bbox = person.get("bbox", {})
|
||||
if bbox.get("width", 0) <= 0 or bbox.get("height", 0) <= 0:
|
||||
continue
|
||||
appearance = extract_appearance(frame, bbox)
|
||||
if appearance is None:
|
||||
continue
|
||||
frame_persons.append(
|
||||
{
|
||||
"person_id": pid,
|
||||
"bbox": bbox,
|
||||
**appearance,
|
||||
}
|
||||
)
|
||||
|
||||
if frame_persons:
|
||||
frames_out.append(
|
||||
{
|
||||
"frame": frame_num,
|
||||
"timestamp": pose_frame.get("timestamp", frame_num / fps),
|
||||
"persons": frame_persons,
|
||||
}
|
||||
)
|
||||
|
||||
cap.release()
|
||||
|
||||
output = {
|
||||
"frame_count": len(frames_out),
|
||||
"fps": fps,
|
||||
"frames": frames_out,
|
||||
}
|
||||
with open(args.output_path, "w") as f:
|
||||
json.dump(output, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"[APPEARANCE] Done: {len(frames_out)} frames")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1
scripts/apply_asr_corrections_v1.11.py
Symbolic link
1
scripts/apply_asr_corrections_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/apply_asr_corrections_v1.11.py
|
||||
1
scripts/asr_benchmark_runner_v1.11.py
Symbolic link
1
scripts/asr_benchmark_runner_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_benchmark_runner_v1.11.py
|
||||
1
scripts/asr_face_stats_v1.11.py
Symbolic link
1
scripts/asr_face_stats_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_face_stats_v1.11.py
|
||||
1
scripts/asr_model_benchmark_v1.11.py
Symbolic link
1
scripts/asr_model_benchmark_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_model_benchmark_v1.11.py
|
||||
1
scripts/asr_processor_base_v1.11.py
Symbolic link
1
scripts/asr_processor_base_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_base_v1.11.py
|
||||
1
scripts/asr_processor_contract_v1_v1.11.py
Symbolic link
1
scripts/asr_processor_contract_v1_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_contract_v1_v1.11.py
|
||||
1
scripts/asr_processor_contract_v2_v1.11.py
Symbolic link
1
scripts/asr_processor_contract_v2_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_contract_v2_v1.11.py
|
||||
1
scripts/asr_processor_debug_v1.11.py
Symbolic link
1
scripts/asr_processor_debug_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_debug_v1.11.py
|
||||
1
scripts/asr_processor_legacy_v1.11.py
Symbolic link
1
scripts/asr_processor_legacy_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_legacy_v1.11.py
|
||||
1
scripts/asr_processor_legacy_v2_v1.11.py
Symbolic link
1
scripts/asr_processor_legacy_v2_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_legacy_v2_v1.11.py
|
||||
1
scripts/asr_processor_simplified_v1.11.py
Symbolic link
1
scripts/asr_processor_simplified_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_simplified_v1.11.py
|
||||
1
scripts/asr_processor_small_multilingual_v1.11.py
Symbolic link
1
scripts/asr_processor_small_multilingual_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_small_multilingual_v1.11.py
|
||||
1
scripts/asr_processor_small_v1.11.py
Symbolic link
1
scripts/asr_processor_small_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_small_v1.11.py
|
||||
1
scripts/asr_processor_v1.11.py
Symbolic link
1
scripts/asr_processor_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_v1.11.py
|
||||
1
scripts/asr_processor_v2_v1.11.py
Symbolic link
1
scripts/asr_processor_v2_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_processor_v2_v1.11.py
|
||||
1
scripts/asr_side_by_side_comparison_v1.11.py
Symbolic link
1
scripts/asr_side_by_side_comparison_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asr_side_by_side_comparison_v1.11.py
|
||||
@@ -228,7 +228,21 @@ def process_asrx(video_path: str, output_path: str, uuid: str = "",
|
||||
# Stage 1: Audio Track Preprocessing
|
||||
tmp_dir, audio_input = _shared_audio_setup(video_path)
|
||||
|
||||
# Stage 2: SelfASRXFixed 7-step pipeline
|
||||
# Stage 2: Load ASR segments for time alignment (if available)
|
||||
asr_segments = None
|
||||
asr_path = (output_path.replace(".asrx.json", ".asr.json")
|
||||
if output_path else "")
|
||||
if asr_path and os.path.exists(asr_path):
|
||||
try:
|
||||
with open(asr_path) as f:
|
||||
asr_data = json.load(f)
|
||||
asr_segments = asr_data.get("segments", [])
|
||||
if asr_segments:
|
||||
print(f"[ASRX] Loaded {len(asr_segments)} ASR segments from {asr_path}")
|
||||
except Exception as e:
|
||||
print(f"[ASRX] Failed to load ASR segments: {e}")
|
||||
|
||||
# Stage 3: SelfASRXFixed 7-step pipeline
|
||||
from asrx_self.main_fixed import SelfASRXFixed
|
||||
|
||||
if publisher:
|
||||
@@ -239,6 +253,9 @@ def process_asrx(video_path: str, output_path: str, uuid: str = "",
|
||||
if publisher:
|
||||
publisher.info("asrx", "ASRX_TRANSCRIBING")
|
||||
|
||||
if asr_segments:
|
||||
print(f"[ASRX] Using {len(asr_segments)} ASR segments for diarization", file=sys.stderr)
|
||||
|
||||
result = asrx.process(
|
||||
audio_input,
|
||||
output_path=None,
|
||||
@@ -246,6 +263,7 @@ def process_asrx(video_path: str, output_path: str, uuid: str = "",
|
||||
max_speakers=10,
|
||||
quality_threshold=0.85,
|
||||
checkpoint_path=checkpoint_path,
|
||||
asr_segments=asr_segments,
|
||||
)
|
||||
|
||||
if "error" in result:
|
||||
|
||||
322
scripts/asrx_processor_custom_v1.11.py
Normal file
322
scripts/asrx_processor_custom_v1.11.py
Normal file
@@ -0,0 +1,322 @@
|
||||
#!/opt/homebrew/bin/python3.11
|
||||
"""
|
||||
ASRX Processor - Custom Implementation Wrapper
|
||||
Uses SpeechBrain ECAPA-TDNN (no HuggingFace token required)
|
||||
|
||||
Pipeline:
|
||||
1. Preprocess: ffprobe audio tracks → select best track → extract WAV
|
||||
2. Process: VAD (Silero) → Speaker embedding (ECAPA-TDNN) → Spectral clustering
|
||||
3. Output: segments with speaker_id
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
sys.path.insert(
|
||||
0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "asrx_self")
|
||||
)
|
||||
|
||||
from redis_publisher import RedisPublisher
|
||||
|
||||
|
||||
def probe_audio_tracks(video_path: str) -> list:
|
||||
"""Use ffprobe to list all audio tracks in the video file."""
|
||||
cmd = [
|
||||
"ffprobe", "-v", "quiet", "-print_format", "json",
|
||||
"-show_streams", "-select_streams", "a", video_path,
|
||||
]
|
||||
try:
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
data = json.loads(result.stdout)
|
||||
tracks = []
|
||||
for stream in data.get("streams", []):
|
||||
track = {
|
||||
"index": stream.get("index"),
|
||||
"codec": stream.get("codec_name"),
|
||||
"language": stream.get("tags", {}).get("language", "und"),
|
||||
"channels": stream.get("channels", 0),
|
||||
"sample_rate": stream.get("sample_rate", "0"),
|
||||
}
|
||||
tracks.append(track)
|
||||
return tracks
|
||||
except Exception as e:
|
||||
print(f"[ASRX] ffprobe failed: {e}")
|
||||
return []
|
||||
|
||||
|
||||
def select_best_track(tracks: list) -> int:
|
||||
"""Select the best audio track: English > first available > fallback to 0."""
|
||||
if not tracks:
|
||||
return 0
|
||||
|
||||
# Priority 1: English track
|
||||
for i, t in enumerate(tracks):
|
||||
if t["language"] == "eng" or t["language"] == "en":
|
||||
print(f"[ASRX] Selected English track (index {t['index']})")
|
||||
return i
|
||||
|
||||
# Priority 2: First track with the most channels
|
||||
best = 0
|
||||
for i, t in enumerate(tracks):
|
||||
if t["channels"] > tracks[best]["channels"]:
|
||||
best = i
|
||||
|
||||
print(f"[ASRX] Selected track {best} (lang={tracks[best]['language']}, ch={tracks[best]['channels']})")
|
||||
return best
|
||||
|
||||
|
||||
def extract_audio_to_wav(video_path: str, track_index: int, output_wav: str) -> bool:
|
||||
"""Extract selected audio track to 16kHz mono WAV using ffmpeg."""
|
||||
cmd = [
|
||||
"ffmpeg", "-y", "-v", "quiet",
|
||||
"-i", video_path,
|
||||
"-map", f"0:{track_index}",
|
||||
"-ar", "16000",
|
||||
"-ac", "1",
|
||||
"-sample_fmt", "s16",
|
||||
output_wav,
|
||||
]
|
||||
try:
|
||||
subprocess.run(cmd, check=True, capture_output=True, timeout=300)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ASRX] ffmpeg extraction failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def _cleanup(tmp_dir):
|
||||
"""Clean up temporary directory."""
|
||||
if tmp_dir and os.path.exists(tmp_dir):
|
||||
import shutil
|
||||
shutil.rmtree(tmp_dir, ignore_errors=True)
|
||||
|
||||
|
||||
def process_asrx_custom(video_path: str, output_path: str, uuid: str = ""):
|
||||
"""Process video for speaker diarization using custom implementation"""
|
||||
|
||||
publisher = RedisPublisher(uuid) if uuid else None
|
||||
if publisher:
|
||||
publisher.info("asrx", "ASRX_START")
|
||||
|
||||
tmp_dir = None
|
||||
|
||||
try:
|
||||
# Ensure working directory is the scripts dir for model loading
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
os.chdir(script_dir)
|
||||
|
||||
# Debug: check ffmpeg availability
|
||||
import shutil
|
||||
ffmpeg_path = shutil.which("ffmpeg")
|
||||
print(f"[ASRX] ffmpeg: {ffmpeg_path}", file=sys.stderr)
|
||||
print(f"[ASRX] CWD: {os.getcwd()}", file=sys.stderr)
|
||||
|
||||
# ---- Stage 1: Audio Track Preprocessing ----
|
||||
print("\n[ASRX] ===== Stage 1: Audio Track Analysis =====", file=sys.stderr)
|
||||
print(f"[ASRX] Input: {video_path}", file=sys.stderr)
|
||||
|
||||
tracks = probe_audio_tracks(video_path)
|
||||
if tracks:
|
||||
print(f"[ASRX] Found {len(tracks)} audio track(s):", file=sys.stderr)
|
||||
for t in tracks:
|
||||
print(f" Track {t['index']}: {t['codec']} {t['channels']}ch {t['sample_rate']}Hz lang={t['language']}", file=sys.stderr)
|
||||
else:
|
||||
print("[ASRX] No audio tracks found via ffprobe, using raw file", file=sys.stderr)
|
||||
|
||||
# Select best track
|
||||
track_idx = select_best_track(tracks) if tracks else 0
|
||||
actual_track_index = tracks[track_idx]["index"] if tracks else track_idx
|
||||
|
||||
# Extract audio to WAV
|
||||
tmp_dir = tempfile.mkdtemp(prefix="asrx_")
|
||||
wav_path = os.path.join(tmp_dir, "audio.wav")
|
||||
|
||||
if extract_audio_to_wav(video_path, actual_track_index, wav_path):
|
||||
wav_size = os.path.getsize(wav_path)
|
||||
print(f"[ASRX] Audio extracted: {wav_path} ({wav_size / 1024 / 1024:.1f}MB)", file=sys.stderr)
|
||||
audio_input = wav_path
|
||||
else:
|
||||
print("[ASRX] Audio extraction failed, falling back to original file", file=sys.stderr)
|
||||
audio_input = video_path
|
||||
|
||||
# ---- Stage 2: Load ASR segments for time alignment ----
|
||||
# Try multiple paths to find ASR JSON
|
||||
asr_segments = []
|
||||
asr_fallback_reason = ""
|
||||
asr_candidates = [
|
||||
output_path.replace(".asrx.json", ".asr.json") if output_path else "",
|
||||
os.path.join(os.path.dirname(output_path) if output_path else ".", os.path.basename(video_path).rsplit(".", 1)[0] + ".asr.json"),
|
||||
os.path.join(os.path.dirname(output_path) if output_path else ".", "dd61fda85fee441fdd00ab5528213ff7.asr.json"),
|
||||
]
|
||||
asr_path = ""
|
||||
for candidate in asr_candidates:
|
||||
if candidate and os.path.exists(candidate):
|
||||
asr_path = candidate
|
||||
break
|
||||
if asr_path:
|
||||
try:
|
||||
with open(asr_path) as f:
|
||||
asr_data = json.load(f)
|
||||
asr_segments = asr_data.get("segments", [])
|
||||
print(f"[ASRX] Loaded {len(asr_segments)} ASR segments from {asr_path}", file=sys.stderr)
|
||||
asr_fallback_reason = f"loaded_{len(asr_segments)}_segments"
|
||||
except Exception as e:
|
||||
asr_fallback_reason = f"load_error_{e}"
|
||||
print(f"[ASRX] Failed to load ASR segments: {e}", file=sys.stderr)
|
||||
else:
|
||||
asr_fallback_reason = f"asr_json_not_found_tried_{len(asr_candidates)}_paths"
|
||||
print(f"[ASRX] ASR output not found, tried {len(asr_candidates)} paths. First candidate: {asr_candidates[0]}", file=sys.stderr)
|
||||
|
||||
# ---- Stage 3: ASRX Processing ----
|
||||
from asrx_self.main_fixed import SelfASRXFixed
|
||||
|
||||
if publisher:
|
||||
publisher.info("asrx", "ASRX_LOADING_MODEL")
|
||||
|
||||
asrx = SelfASRXFixed()
|
||||
|
||||
if publisher:
|
||||
publisher.info("asrx", "ASRX_TRANSCRIBING")
|
||||
|
||||
if asr_segments:
|
||||
print(f"[ASRX] Using {len(asr_segments)} ASR segments for diarization", file=sys.stderr)
|
||||
|
||||
result = asrx.process(
|
||||
audio_input,
|
||||
output_path=None,
|
||||
max_speakers=10,
|
||||
asr_segments=asr_segments if asr_segments else None,
|
||||
)
|
||||
|
||||
if "error" in result:
|
||||
if publisher:
|
||||
publisher.error("asrx", result["error"])
|
||||
|
||||
# Return empty result
|
||||
output_result = {"language": None, "segments": []}
|
||||
|
||||
with open(output_path, "w") as f:
|
||||
json.dump(output_result, f, indent=2)
|
||||
|
||||
if publisher:
|
||||
publisher.complete("asrx", "0 segments")
|
||||
|
||||
_cleanup(tmp_dir)
|
||||
return output_result
|
||||
|
||||
# Convert to Rust-expected format (start_frame/end_frame/speaker)
|
||||
# Read fps from probe json ({file_uuid}.probe.json)
|
||||
_debug = {"asr_fallback": asr_fallback_reason, "asr_path": asr_path}
|
||||
fps = 30.0
|
||||
output_dir = os.path.dirname(output_path) if output_path else "."
|
||||
base_name = os.path.basename(output_path) if output_path else ""
|
||||
# Extract uuid from {uuid}.{type}.json format
|
||||
uuid_part = base_name.split(".")[0] if base_name else ""
|
||||
probe_candidates = [
|
||||
os.path.join(output_dir, f"{uuid_part}.probe.json"),
|
||||
]
|
||||
for p in probe_candidates:
|
||||
if os.path.exists(p):
|
||||
try:
|
||||
with open(p) as pf:
|
||||
probe_data = json.load(pf)
|
||||
if "fps" in probe_data:
|
||||
fps = float(probe_data["fps"])
|
||||
print(f"[ASRX] FPS from probe: {fps}", file=sys.stderr)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
output_result = {
|
||||
"language": None,
|
||||
"segments": [],
|
||||
}
|
||||
|
||||
# Convert segments
|
||||
for seg in result["segments"]:
|
||||
start_sec = seg["start"]
|
||||
end_sec = seg["end"]
|
||||
output_result["segments"].append(
|
||||
{
|
||||
"start_time": start_sec,
|
||||
"end_time": end_sec,
|
||||
"start_frame": int(start_sec * fps),
|
||||
"end_frame": int(end_sec * fps),
|
||||
"text": "",
|
||||
"speaker_id": seg["speaker"],
|
||||
}
|
||||
)
|
||||
|
||||
# Add speaker_stats as optional metadata
|
||||
if "speaker_stats" in result:
|
||||
output_result["speaker_stats"] = result["speaker_stats"]
|
||||
|
||||
# 傳遞 embeddings(每個 segment 對應的 192-D speaker embedding)
|
||||
if "embeddings" in result:
|
||||
output_result["embeddings"] = result["embeddings"]
|
||||
|
||||
if publisher:
|
||||
publisher.info("asrx", f"ASRX_COMPLETE:{len(output_result['segments'])}")
|
||||
|
||||
# Save output
|
||||
output_result["_debug"] = _debug
|
||||
with open(output_path, "w") as f:
|
||||
json.dump(output_result, f, indent=2)
|
||||
|
||||
if publisher:
|
||||
publisher.complete("asrx", f"{len(output_result['segments'])} segments")
|
||||
|
||||
print(f"[ASRX-Custom] Saved {len(output_result['segments'])} segments to {output_path}", file=sys.stderr)
|
||||
|
||||
_cleanup(tmp_dir)
|
||||
return output_result
|
||||
|
||||
except Exception as e:
|
||||
if publisher:
|
||||
publisher.error("asrx", str(e))
|
||||
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
|
||||
# Return empty result on error
|
||||
output_result = {"language": None, "segments": []}
|
||||
|
||||
with open(output_path, "w") as f:
|
||||
json.dump(output_result, f, indent=2)
|
||||
|
||||
if publisher:
|
||||
publisher.complete("asrx", "0 segments")
|
||||
|
||||
_cleanup(tmp_dir)
|
||||
return output_result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="ASRX Processor (Custom Implementation)"
|
||||
)
|
||||
parser.add_argument("video_path", help="Path to video/audio file")
|
||||
parser.add_argument("output_path", help="Path to output JSON file")
|
||||
parser.add_argument("--uuid", help="UUID for Redis publishing", default="")
|
||||
parser.add_argument("--file-uuid", help="File UUID (deprecated, use --uuid)", default="")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not Path(args.video_path).exists():
|
||||
print(f"Error: Video file not found: {args.video_path}")
|
||||
sys.exit(1)
|
||||
|
||||
result = process_asrx_custom(args.video_path, args.output_path, args.uuid)
|
||||
|
||||
print("\n[Summary]")
|
||||
print(f" Total segments: {len(result['segments'])}")
|
||||
if "speaker_stats" in result:
|
||||
print(f" Detected speakers: {len(result['speaker_stats'])}")
|
||||
for speaker, stats in result["speaker_stats"].items():
|
||||
print(f" {speaker}: {stats['count']} segments")
|
||||
1
scripts/asrx_processor_v1.11.py
Symbolic link
1
scripts/asrx_processor_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/asrx_processor_v1.11.py
|
||||
@@ -170,7 +170,7 @@ class SelfASRXFixed:
|
||||
|
||||
def process(self, audio_path, output_path=None, file_uuid=None,
|
||||
max_speakers=10, quality_threshold=0.85,
|
||||
checkpoint_path=None):
|
||||
checkpoint_path=None, asr_segments=None):
|
||||
"""7 步 speaker diarization pipeline
|
||||
|
||||
Args:
|
||||
@@ -180,6 +180,7 @@ class SelfASRXFixed:
|
||||
max_speakers: 最大說話人數
|
||||
quality_threshold: 高品質聲紋門檻 (0-1)
|
||||
checkpoint_path: Step 3 完成後儲存 checkpoint 路徑
|
||||
asr_segments: 外部 ASR segments (from asr.json),跳過 Step 1
|
||||
|
||||
Returns:
|
||||
dict: segments, speaker_stats, n_speakers, total_duration, references
|
||||
@@ -194,16 +195,21 @@ class SelfASRXFixed:
|
||||
print(f" Audio: {total_duration:.2f}s, {sample_rate}Hz")
|
||||
|
||||
# ── Step 1: whisper 粗略定位 (faster-whisper) ──
|
||||
print("\n[Step 1] Initial whisper transcription...")
|
||||
t1 = time.time()
|
||||
seg_gen, info = self.whisper.transcribe(audio_path)
|
||||
rough_segments = []
|
||||
for seg in seg_gen:
|
||||
rough_segments.append({"start": seg.start, "end": seg.end, "text": seg.text})
|
||||
language = info.language if info else None
|
||||
print(f" Rough segments: {len(rough_segments)}")
|
||||
print(f" Language: {language}")
|
||||
print(f" Step 1 time: {time.time() - t1:.2f}s")
|
||||
if asr_segments:
|
||||
print(f"\n[Step 1] Skipping whisper, using {len(asr_segments)} provided ASR segments")
|
||||
rough_segments = asr_segments
|
||||
language = asr_segments[0].get("language") if isinstance(asr_segments[0].get("language"), str) else None
|
||||
else:
|
||||
print("\n[Step 1] Initial whisper transcription...")
|
||||
t1 = time.time()
|
||||
seg_gen, info = self.whisper.transcribe(audio_path)
|
||||
rough_segments = []
|
||||
for seg in seg_gen:
|
||||
rough_segments.append({"start": seg.start, "end": seg.end, "text": seg.text})
|
||||
language = info.language if info else None
|
||||
print(f" Rough segments: {len(rough_segments)}")
|
||||
print(f" Language: {language}")
|
||||
print(f" Step 1 time: {time.time() - t1:.2f}s")
|
||||
|
||||
if not rough_segments:
|
||||
print("[SelfASRX] No speech detected by whisper!")
|
||||
|
||||
1
scripts/audio_taxonomy_processor_v1.11.py
Symbolic link
1
scripts/audio_taxonomy_processor_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/audio_taxonomy_processor_v1.11.py
|
||||
1
scripts/audio_taxonomy_processor_v2_v1.11.py
Symbolic link
1
scripts/audio_taxonomy_processor_v2_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/audio_taxonomy_processor_v2_v1.11.py
|
||||
1
scripts/auto_identify_persons_v1.11.py
Symbolic link
1
scripts/auto_identify_persons_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/auto_identify_persons_v1.11.py
|
||||
1
scripts/backfill_demographics_v1.11.py
Symbolic link
1
scripts/backfill_demographics_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/backfill_demographics_v1.11.py
|
||||
76
scripts/backfill_face_id.py
Normal file
76
scripts/backfill_face_id.py
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/opt/homebrew/bin/python3.11
|
||||
"""Backfill face_id for existing face_detections rows using trace_id.
|
||||
|
||||
face_id is generated as 'face_{trace_id}' for each unique trace.
|
||||
This covers past data where face_id was never written.
|
||||
"""
|
||||
|
||||
import os
|
||||
import psycopg2
|
||||
|
||||
DB_URL = os.environ.get("DATABASE_URL", "postgresql://accusys@localhost:5432/momentry")
|
||||
SCHEMA = os.environ.get("MOMENTRY_DB_SCHEMA", "dev")
|
||||
|
||||
|
||||
def get_conn():
|
||||
return psycopg2.connect(DB_URL)
|
||||
|
||||
|
||||
def backfill_by_trace(file_uuid: str, schema: str = SCHEMA) -> int:
|
||||
"""Set face_id = 'face_{trace_id}' for all rows with NULL face_id and non-NULL trace_id."""
|
||||
conn = get_conn()
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute(
|
||||
f"""
|
||||
UPDATE {schema}.face_detections
|
||||
SET face_id = 'face_' || trace_id::text
|
||||
WHERE file_uuid = %s
|
||||
AND face_id IS NULL
|
||||
AND trace_id IS NOT NULL
|
||||
""",
|
||||
(file_uuid,),
|
||||
)
|
||||
updated = cur.rowcount
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
return updated
|
||||
|
||||
|
||||
def main():
|
||||
conn = get_conn()
|
||||
cur = conn.cursor()
|
||||
|
||||
# Count rows that need backfill
|
||||
cur.execute(
|
||||
f"""SELECT COUNT(*) FROM {SCHEMA}.face_detections
|
||||
WHERE face_id IS NULL AND trace_id IS NOT NULL"""
|
||||
)
|
||||
total_rows = cur.fetchone()[0]
|
||||
|
||||
cur.execute(
|
||||
f"""SELECT DISTINCT file_uuid FROM {SCHEMA}.face_detections
|
||||
WHERE face_id IS NULL AND trace_id IS NOT NULL"""
|
||||
)
|
||||
uuids = [row[0] for row in cur.fetchall()]
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
if not uuids:
|
||||
print("No rows need backfill (all face_id already set or no trace_id).")
|
||||
return
|
||||
|
||||
print(f"Found {total_rows} rows across {len(uuids)} files to backfill")
|
||||
|
||||
total_all = 0
|
||||
for uuid in uuids:
|
||||
count = backfill_by_trace(uuid)
|
||||
total_all += count
|
||||
print(f" [{uuid}] updated {count} rows")
|
||||
|
||||
print(f"\nDone: {len(uuids)} files, {total_all} rows updated")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1
scripts/backfill_frame_data_v1.11.py
Symbolic link
1
scripts/backfill_frame_data_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/backfill_frame_data_v1.11.py
|
||||
1
scripts/build_docs_v1.11.py
Symbolic link
1
scripts/build_docs_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/build_docs_v1.11.py
|
||||
1
scripts/build_semantic_index_poc_v1.11.py
Symbolic link
1
scripts/build_semantic_index_poc_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/build_semantic_index_poc_v1.11.py
|
||||
1
scripts/build_semantic_index_v1.11.py
Symbolic link
1
scripts/build_semantic_index_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/build_semantic_index_v1.11.py
|
||||
1
scripts/bvh_exporter_v1.11.py
Symbolic link
1
scripts/bvh_exporter_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/bvh_exporter_v1.11.py
|
||||
1
scripts/caption_processor_contract_v1_v1.11.py
Symbolic link
1
scripts/caption_processor_contract_v1_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/caption_processor_contract_v1_v1.11.py
|
||||
1
scripts/caption_processor_v1.11.py
Symbolic link
1
scripts/caption_processor_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/caption_processor_v1.11.py
|
||||
1
scripts/check_all_stamps_v1.11.py
Symbolic link
1
scripts/check_all_stamps_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/check_all_stamps_v1.11.py
|
||||
1
scripts/check_architecture_all_v1.11.py
Symbolic link
1
scripts/check_architecture_all_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/check_architecture_all_v1.11.py
|
||||
1
scripts/check_architecture_docs_v1.11.py
Symbolic link
1
scripts/check_architecture_docs_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/check_architecture_docs_v1.11.py
|
||||
1
scripts/check_code_document_consistency_v1.11.py
Symbolic link
1
scripts/check_code_document_consistency_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/check_code_document_consistency_v1.11.py
|
||||
1
scripts/check_frame_112_36_v1.11.py
Symbolic link
1
scripts/check_frame_112_36_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/check_frame_112_36_v1.11.py
|
||||
1
scripts/check_frame_91_59_v1.11.py
Symbolic link
1
scripts/check_frame_91_59_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/check_frame_91_59_v1.11.py
|
||||
1
scripts/chinese_vector_test_v1.11.py
Symbolic link
1
scripts/chinese_vector_test_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/chinese_vector_test_v1.11.py
|
||||
1
scripts/chunk_statistics_v1.11.py
Symbolic link
1
scripts/chunk_statistics_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/chunk_statistics_v1.11.py
|
||||
1
scripts/clean_sentence_text_v1.11.py
Symbolic link
1
scripts/clean_sentence_text_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/clean_sentence_text_v1.11.py
|
||||
1
scripts/clip_classifier_v1.11.py
Symbolic link
1
scripts/clip_classifier_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/clip_classifier_v1.11.py
|
||||
1
scripts/clip_logo_integration_v1.11.py
Symbolic link
1
scripts/clip_logo_integration_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/clip_logo_integration_v1.11.py
|
||||
1
scripts/compare_asr_content_v1.11.py
Symbolic link
1
scripts/compare_asr_content_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/compare_asr_content_v1.11.py
|
||||
1
scripts/compare_asr_models_v1.11.py
Symbolic link
1
scripts/compare_asr_models_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/compare_asr_models_v1.11.py
|
||||
1
scripts/compare_models_gun_test_v1.11.py
Symbolic link
1
scripts/compare_models_gun_test_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/compare_models_gun_test_v1.11.py
|
||||
1
scripts/compare_search_v1.11.py
Symbolic link
1
scripts/compare_search_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/compare_search_v1.11.py
|
||||
1
scripts/compare_segmentation_v1.11.py
Symbolic link
1
scripts/compare_segmentation_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/compare_segmentation_v1.11.py
|
||||
1
scripts/comprehensive_search_test_v1.11.py
Symbolic link
1
scripts/comprehensive_search_test_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/comprehensive_search_test_v1.11.py
|
||||
1
scripts/coreml_embed_server_v1.11.py
Symbolic link
1
scripts/coreml_embed_server_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/coreml_embed_server_v1.11.py
|
||||
1
scripts/crop_opencv_stamp_v1.11.py
Symbolic link
1
scripts/crop_opencv_stamp_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/crop_opencv_stamp_v1.11.py
|
||||
1
scripts/crop_real_stamps_v1.11.py
Symbolic link
1
scripts/crop_real_stamps_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/crop_real_stamps_v1.11.py
|
||||
1
scripts/crop_stamp_112_36_v1.11.py
Symbolic link
1
scripts/crop_stamp_112_36_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/crop_stamp_112_36_v1.11.py
|
||||
1
scripts/crop_stamp_closeup_v1.11.py
Symbolic link
1
scripts/crop_stamp_closeup_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/crop_stamp_closeup_v1.11.py
|
||||
1
scripts/crop_stamp_v1.11.py
Symbolic link
1
scripts/crop_stamp_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/crop_stamp_v1.11.py
|
||||
1
scripts/crop_top_candidates_v1.11.py
Symbolic link
1
scripts/crop_top_candidates_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/crop_top_candidates_v1.11.py
|
||||
1
scripts/cut_benchmark_runner_v1.11.py
Symbolic link
1
scripts/cut_benchmark_runner_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/cut_benchmark_runner_v1.11.py
|
||||
1
scripts/cut_processor_contract_v1_v1.11.py
Symbolic link
1
scripts/cut_processor_contract_v1_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/cut_processor_contract_v1_v1.11.py
|
||||
1
scripts/cut_processor_v1.11.py
Symbolic link
1
scripts/cut_processor_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/cut_processor_v1.11.py
|
||||
1
scripts/dashboard_v1.11.py
Symbolic link
1
scripts/dashboard_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/dashboard_v1.11.py
|
||||
1
scripts/debug_face_registration_v1.11.py
Symbolic link
1
scripts/debug_face_registration_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/debug_face_registration_v1.11.py
|
||||
1
scripts/deep_analysis_112_36_v1.11.py
Symbolic link
1
scripts/deep_analysis_112_36_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/deep_analysis_112_36_v1.11.py
|
||||
1
scripts/demo_dashboard_v1.11.py
Symbolic link
1
scripts/demo_dashboard_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/demo_dashboard_v1.11.py
|
||||
1
scripts/demo_face_learning_v1.11.py
Symbolic link
1
scripts/demo_face_learning_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/demo_face_learning_v1.11.py
|
||||
1
scripts/dense_scan_traces_v1.11.py
Symbolic link
1
scripts/dense_scan_traces_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/dense_scan_traces_v1.11.py
|
||||
1
scripts/detect_language_v1.11.py
Symbolic link
1
scripts/detect_language_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/detect_language_v1.11.py
|
||||
1
scripts/detect_objects_keyframes_v1.11.py
Symbolic link
1
scripts/detect_objects_keyframes_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/detect_objects_keyframes_v1.11.py
|
||||
1
scripts/detect_stamp_shapes_v1.11.py
Symbolic link
1
scripts/detect_stamp_shapes_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/detect_stamp_shapes_v1.11.py
|
||||
1
scripts/download_places365_classes_v1.11.py
Symbolic link
1
scripts/download_places365_classes_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/download_places365_classes_v1.11.py
|
||||
1
scripts/e4b_per_cut_v1.11.py
Symbolic link
1
scripts/e4b_per_cut_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/e4b_per_cut_v1.11.py
|
||||
1
scripts/embed_faces_only_v1.11.py
Symbolic link
1
scripts/embed_faces_only_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/embed_faces_only_v1.11.py
|
||||
1
scripts/embed_faces_v1.11.py
Symbolic link
1
scripts/embed_faces_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/embed_faces_v1.11.py
|
||||
1
scripts/embeddinggemma_server_v1.11.py
Symbolic link
1
scripts/embeddinggemma_server_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/embeddinggemma_server_v1.11.py
|
||||
1
scripts/export_file_package_v1.11.py
Symbolic link
1
scripts/export_file_package_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/export_file_package_v1.11.py
|
||||
1
scripts/export_file_v1.11.py
Symbolic link
1
scripts/export_file_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/export_file_v1.11.py
|
||||
1
scripts/export_identities_v1.11.py
Symbolic link
1
scripts/export_identities_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/export_identities_v1.11.py
|
||||
1
scripts/export_person_thumbnails_v1.11.py
Symbolic link
1
scripts/export_person_thumbnails_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/export_person_thumbnails_v1.11.py
|
||||
1
scripts/export_sqlite_v1.11.py
Symbolic link
1
scripts/export_sqlite_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/export_sqlite_v1.11.py
|
||||
1
scripts/extract_embeddings_from_face_json_v1.11.py
Symbolic link
1
scripts/extract_embeddings_from_face_json_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/extract_embeddings_from_face_json_v1.11.py
|
||||
1
scripts/extract_face_crops_v1.11.py
Symbolic link
1
scripts/extract_face_crops_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/extract_face_crops_v1.11.py
|
||||
1
scripts/extract_face_embedding_v1.11.py
Symbolic link
1
scripts/extract_face_embedding_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/extract_face_embedding_v1.11.py
|
||||
1
scripts/extract_female_faces_v1.11.py
Symbolic link
1
scripts/extract_female_faces_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/extract_female_faces_v1.11.py
|
||||
1
scripts/extract_video_embeddings_v1.11.py
Symbolic link
1
scripts/extract_video_embeddings_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/extract_video_embeddings_v1.11.py
|
||||
1
scripts/face_benchmark_runner_v1.11.py
Symbolic link
1
scripts/face_benchmark_runner_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_benchmark_runner_v1.11.py
|
||||
1
scripts/face_clustering_processor_v1.11.py
Symbolic link
1
scripts/face_clustering_processor_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_clustering_processor_v1.11.py
|
||||
1
scripts/face_count_comparison_v1.11.py
Symbolic link
1
scripts/face_count_comparison_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_count_comparison_v1.11.py
|
||||
1
scripts/face_cross_validate_v1.11.py
Symbolic link
1
scripts/face_cross_validate_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_cross_validate_v1.11.py
|
||||
1
scripts/face_embedding_extractor_v1.11.py
Symbolic link
1
scripts/face_embedding_extractor_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_embedding_extractor_v1.11.py
|
||||
1
scripts/face_landmark_qc_v1.11.py
Symbolic link
1
scripts/face_landmark_qc_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_landmark_qc_v1.11.py
|
||||
1
scripts/face_mediapipe_test_v1.11.py
Symbolic link
1
scripts/face_mediapipe_test_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_mediapipe_test_v1.11.py
|
||||
1
scripts/face_processor_contract_v1_v1.11.py
Symbolic link
1
scripts/face_processor_contract_v1_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_processor_contract_v1_v1.11.py
|
||||
1
scripts/face_processor_mps_v1.11.py
Symbolic link
1
scripts/face_processor_mps_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_processor_mps_v1.11.py
|
||||
1
scripts/face_processor_optimized_v1.11.py
Symbolic link
1
scripts/face_processor_optimized_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_processor_optimized_v1.11.py
|
||||
1
scripts/face_processor_v1.11.py
Symbolic link
1
scripts/face_processor_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_processor_v1.11.py
|
||||
1
scripts/face_processor_v1_v1.11.py
Symbolic link
1
scripts/face_processor_v1_v1.11.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../v1.1/scripts/face_processor_v1_v1.11.py
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user