我有一台松下相机 (DC-FZ82),它能够通过自己的 WLAN 传输实时取景。我编写了一个向相机发送http请求的程序(如下所示:http://192.168.54.1/cam.cgi?mode=getstate)。要启动liev View,请发送此命令http://192.168.54.1/cam.cgi?mode=startstream&value=49152,然后摄像机开始将带有UPD的实时视图从其端口(65428)发送到我的端口49152 。
我的问题是我不知道如何处理从
data, address = sock.recvfrom(max_length)
收到的数据,以便可以将其显示为实时视频。
谢谢您,并对混乱的代码表示歉意:
import cv2
import numpy as np
import requests
import pickle
import socket
import time
host = '192.168.54.10'
port = 49152
max_length = 30000
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((host, port))
frame_info = None
buffer = None
frame = None
# Die IP-Adresse der Kamera
camera_ip = "192.168.54.1"
commands=["mode=setsetting&type=device_name&value=MI%205",
"mode=camcmd&value=playmode",
"mode=camcmd&value=video_recstart",
"mode=camcmd&value=video_recstop",
"mode=camcmd&value=capture",
"mode=getstate",
"mode=setsetting&type=iso&value=80",
"mode=camctrl&type=touch&value=0/0&value2=on",
"mode=camcmd&value=touchafrelease",
"mode=startstream&value=49152",
"mode=accctrl&type=req_acc&value=4D454930-0100-1000-8000-A0C9A018A734&value2=SM-G9350",
"mode=setsetting&type=device_name&value=SM-G9350",
"mode=getinfo&type=allmenu",
"mode=getinfo&type=curmenu",
"mode=camcmd&value=recmode",
"mode=getinfo&type=lens"]
# Funktion, um einen Befehl an die Kamera zu senden und das Ergebnis zurückzugeben - function for sending a commad to the cam
def send_command(command):
url = f"http://{camera_ip}/cam.cgi?" + command
response = requests.get(url)
print(url)
print(response.text)
return response.text
if True:
while True:
# Befehle anzeigen
for i, command in enumerate(commands):
print(f"{i}: {command}")
# Eingabeaufforderung anzeigen und Eingabe vom Benutzer lesen - Read user input
choice = input("Befehl eingeben: ")
# Befehl auswählen und an die Kamera senden - choose command and send to cam
if choice.isdigit() and int(choice) < len(commands):
send_command(commands[int(choice)])
elif choice.isdigit() and int(choice)==99:
break
else:
send_command(choice)
# Live-Video anzeigen - show live view
if choice.isdigit() and int(choice) == 9:
while True:
#print("True")
data, address = sock.recvfrom(max_length)
#print("Adresse: ")
#print(address)
print("Daten: ")
print(data)
print(len(data))
if len(data) < 28000:
frame_info = pickle.loads(data)
print("Frame_info:")
print(frame_info)
print("len(data) < 100")
if frame_info:
nums_of_packs = frame_info["packs"]
for i in range(nums_of_packs):
print("Data, address = sock.recvfrom")
data, address = sock.recvfrom(max_length)
if i == 0:
buffer = data
else:
buffer += data
frame = np.frombuffer(buffer, dtype=np.uint8)
frame = frame.reshape(frame.shape[0], 1)
frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
frame = cv2.flip(frame, 1)
if frame is not None and type(frame) == np.ndarray:
print("streaming...")
cv2.imshow("Stream", frame)
if cv2.waitKey(1) == 27:
break
cap.release()
cv2.destroyAllWindows()
time.sleep(1)
来自“打印(数据)”的数据:
b'f\x1a\x01\x00\x00\x00\x00\x00\x00\xa0\xc9\xa0\x18\xa74\x00!\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x92\x00\n\x00\n\x00\x01H\xff`\xff\x01\x01\x01@\xbb\x00\x06\x00\x01\x00\x02\xf9\x01\x00\x02\xf9\x01\x00\x0b\x00\x01\x00\xfe\x00\x01\x00\x07\x00\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x00\x14\x00\xff\x01*M\t\x00\x00\x01\x00\x01\x00\x00\x00,\x00\x07\x01\x00\x02\x01\x00\x03\x06\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x01\x0f\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x03\x00\xff\xd8\xff\xdb\x00\x84\x00\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x10\x10\x08\x18\x10\x10\x10\x10\x10 \x10\x18\x18\x18\x10 ((( (((008@0008(0H888@@HH(HP8PPPHH@HH\x01\x10\x08\x10\x10\x10\x10\x10 \x100H0(HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH\xff\xc0\x00\x11\x08\x01h\x02\x80\x03\x01!\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x01\xa2\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01}\x01\x02\x03\x00\x04\x11\x05\x12!1A\x06\x13Qa\x07"q\x142\x81\x91\xa1\x08#B\xb1\xc1\x15R\xd1\xf0$3br\x82\t\n\x16\x17\x18\x19\x1a%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\x01\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x11\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02w\x00\x01\x02\x03\x11\x04\x05!1\x06\x12AQ\x07aq\x13"2\x81\x08\x14B\x91\xa1\xb1\xc1\t#3R\xf0\x15br\xd1\n\x16$4\xe1%\xf1\x17\x18\x19\x1a&\'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xff\xdd\x00\x04\x00\x00\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00?\x00\xf3\x11\x9c\xf5\x14\xa7\xd7\x07\x1e\xd5\x95\x9a\xb9\xbd\xc6g\x92x\xa4\xc8\xe3\x9e\xb56\xf2\x1a\x1e\x0f\xd6\x9cNzS]\x01\x8d=\x0f\xb50\xe3\'\xde\x93\xdfq\x88\x0ep)\xf9\xcf>\xb5Q\x10\xfc\xfab\x90\x9cz\xd2\x01\xb9\xe9K\xbb\xd8\xd1\xa0\\3\xda\x94\xe4\x0c\x9aK\xa8w\x138\xe0w\xedJ\x0fa\xdf\xebC\xf5\x0b\x81\xe3\'\x9ei3\xcfSF\xddA\x8a\x1b\x8f\xce\x8c\xe4~T\xc0p\xe7\xad7=\xe90c\x81\xcey\x1cQ\xc6z\xfbS[\x05\xc6\xf7\xcf\xf2\xa7\x12\x01\xea8\xefDu\xea\x0cL\xf3\xd4s\xfa\xd1\x9fqC\xea\t\xe8\x1c\xf4\xcd\x1dh@\xf7\x17?\xad\x19\xef\x9akq\xa13\xce\x7f:NqR\xc1\x07\xe1\xfc\xe8\'\xbehk`\x1c3\xc1\xfet\xa0\xf3\xf4\xa7\r\xc3qH\xef\xc7\xad \xc9\x14\x90\x0b\xd8~T\xa2\x98\x0b\xef\xc5/\xe5In\x0cS\xecsJ\x0eh\xb8\x0e\xe6\x97\x1c\x8aN\xe0.3\xd4\xd3\xb1B\x06D\xe0g\xebN^\xb4\x0c~:\x93\x9aLs\xc7\xd6\x92z\x00\xa3<t\xe2\x9f\x8e;R\xea\x03:\x9e\xb5aE\x1dF\xc91\x9eqK\x8e\xde\xb4\xc4\x1b})\xdbz\xe2\x9a\xf5\x01\xa0s\xcdM\x9c\x0c\xe2\xabp\xd0\x81\x8f\'\x9e\xb4\xe5\x1c\xe3\xd6\x92\xd8\xb4N\xbd\x89>\x94\xf3\xf7y\xa44=\x14\x9cg\xbdN\xee#\xd8\x9cs\x9f\xe5Ik$)\xbb\\\xe7\x95\xcb2\xb1=MX=OJ\xda\xb8\xf2\x9d]A\xbf\\\xf1K\xef\x83\xcdg\xf3;\x99\x04\xb3\xac[A#-\xfc\xab~\xd2\xf9nQ\x12\xdf\x80\x83\x04\xb6q\x9f\xa0\xad(/#\xcf\xcd\xaa]\xa8\xdc\x96W\x9ehd\x8f\xce\xd9\xb3\x9c\xaey\xfc\xeb\x83\xd4L{\xf0&\x99\xd8\x7f{\x15\xb6\x968\xd1(bO$\xd0\x08\xe0\xf1\\\xceF\xed\x01\xeb\x9fN\xf4\xd3\x91\x8a\x18\\]\xd8\xce\x7f\xa5;\'\xf2\xfchZ\xf5)\x81\xeb\x8ai\xf4\xf4\xf4\xa2B\x13\xd8v\xa3=\xbfJ\x1f\xa8\x0e\xcf\x07\x9fJ\x0f\xd6\x95\xac\x01\x93\xfc\xc57#<\xf7\xa7\xa5\xc1\x0e\x078\x14\xa0\x8f^\x94\xd0;j\x19\xa0z\xfdi|\xc4\xde\x82\x93\xeb\xfeM#w\xc5\x1aj\x1a\xd8L\xf4\'?\xfdj3\xc9\xa4\xae\x03\x814\xa7\x9e\xddh]F&H \xfaR\xe7\xb8\xa7\x1d\xc1\x8b\x9f\xa5!\xea}\xbe\xb4D\x1d\xc6\xe7\x81K\xbb\xb7qC\xea\x0ba}\x08\xa3=x\xebM\xee\x0e\xc1\xcfL\x9a:\xfe4\x93\xdf@\x13\x9c\xf7\xe6\x8e\x84`P\xf5@(\xe3>\xdf\xce\x90\x1e\xd9\xa5\xdbPC\xf1\x9e\xfd)G\xe1M\x82\xd0^\xbf\x8d\'J@\xc7u\xe0\xd2\xf0\x7f\x1am\xf9\x8fq\xdd\x8d\x02\x96\xc0;\x06\x97\x19\xe2\xa4\x05\xc1\xe6\x9d\x8f\xd2\x9b\xb5\xd8n(\xeb\xc8\x14\xfcR`F\xc3&\x91?\x1aoD\x86I\x82\x00\xa4#\xb5!\n\xa2\xa4#\x8eM\x0b\xa8\xc8\xc0\xf9\xbe\x95eT\xfa\xd2i\x0c~?ZP;\xfa\xd0\xac\'q\xd8\xfa\xf3R\xe0\x1e*\xba\x8a\xe48\xa5&\x9e\xc8h`\xe7?\x8dJ\xa3\xf5\xa7\'\xa6\xe5\xd8\x9c\x0c\xf1\x8a\x95S"\xa1\xe9pd\xd8X\xd7q\xc7\x1e\xb5\xce\x1b\xef7R\x8e0A\x03\xcc\xc8?\xee\x9at\x15\xe4Ewh\xb28\xb1\xfb\xb3W\x0f>\xb5\xb5SL\x9f\xed\x8d\xc7\xd7\x8f\xca\x98\xecW\x85\\\xb3}\xd1\xefYY\xb6\x8e\xd95\x14\xcc\x99\xf2\xad\x99U\xcb7QZ6W*\xa7\x11\xab.\x07$`\x9a\xde\xd6H\xf1\xaa\xb7)7\xdc\x9aO\x12\xdd\xdb\x83\x0f\x97\t\'\x90\xc0\xe4\xd75su%\xcc\x8f4\xc7,\xfd\xbd(OQT\x8b\x83\xb3e\xb2{\xe0\x8c\xd1\x9cq\x8a\xc5\x9b\x0b\x9e\xa74P\xef\xdc7\x1b\xec{\xd0A\x00Q+\\\x1e\xc3\x81<\xe6\x94\x9fsK{\r\x0c\'\xb1\xa4\xe4q\x9f\xff\x00]T\x96\xfa\x88PI=\xe9s\xd3\xf1\xa4\x95\xfa\x80\x0e\xe2\x8e\xc7${\xd3w\x0e\xafA\t\xf5\xc5.z\xd2\xe9\xb8u\x1d\x9fznO?\x85\t\xd8\x19&OjC\xc9\xa1Z\xe0\xc4\xe0\x8e\xff\x00\xa57>\x82\x89n\x03\x81\xc58\x10x\xcd-;\x8c\x0e=i\x0eG\xaei\xbdC@\x07\x9f\xa5;\xaf>\xbfZkf\'\xea4\xe0\x9a\x018\xfa\xd2\x04\xc5\xeci(\x93\xbd\x80vs\x93FO \xf6\xa3^\xe0/<\xf4\xe6\x90\n\x18\xd8\x13\xd4R\xe3\xbe)\x00\xeeq\xd7\xa5\x07\xa56\x02\x8f\xa7J^OJ[\x80\xa0w\xc5(\xe3\xa5\x008\x0fZP;\xd4\x8cp\xf6\xc7?\x8d\x1e\xfcS@\xf7\x1eG_z1\xcd\x0e\xfa\x82\x1d\x8c\xf1\xeb\xfc\xaa\\g\xad\x00\xc8\xdcz\xf7\xa4\x02\x94\x81\x12c#>\xb4m\xedI\x8d\x00^\x9d)\xec8\xa4\xb7\x01\x8a\xb5e@\x1d\xa9\xb1\x92c\xd7\xbd.?Z/a|\xc3o\xe9N\xfaU&\x0cLg$w\xa8\xdb\x04\xe7\xd6\x9az\x84\x04\x03\x91\x8a\x9d{\x1c\xd2\x93\xbd\xcb\'^\xdf\xfdz\xb2\x8b\xdd\xb1P\xc1\x98:\xbe\xa4\xb1\xa9\x8d\x1b\x9fj\xe74}\xd3j\nI<\x89I\xc7\xfb\xa6\xb7\xc3++\xf79\xf1O\xa1\xac\x84\xe6\x01\xefZ\x04~\xbfZx\x9d\xd1\xd3\x93\xedPa\x15#\xdb*\xaf\x98\xce\xc0\xe0\x81\x83\xd0R\xa0\x9bf\x99\xa4\xf9i\xdb\xb9\xcd]]|\xcd\x1c[03\x82+<\xbb\x11\x8d\xcd\x83\xda\xb4\x93<\xd13I\x93\x9eH\xa0\r~01M\xc7\x1f^\xf5\x8d\xfc\xcd\xa4\x1e\xf8\xebJ\x0f\x7f_\xe7Oq\xa198\xe3\xad\x1cu\xc5(\x83\xd8L\xf2\x0eG\xebN\x04v4k\xdc.!\xebHq\xc7\x18\xe9F\xb7` \xcf\'=iA\xeeq\xf8\xd0\xac\x81\\\\\xfa\x8aJ\x1fQ\x89\xedJ\x0e:\xe6\x87\xd4Hu(4\t\xbb\x06z\xf3N\xcf\xafz4\x1d\xc6\x90{v\xa3\xafS@\x98r{\xf4\xa7d\xe79\x14$;\x0e\x078$\xf5\xa4\xf4\xc68\xe74.\xa1p#\xdc\xd2p2@\xfc\xe9\xec\'\xb0\x1cz\x8a1\xc9\xeb\xcd\x17\xf2\x01s\x9fZ8\xc9\xcfjCh\x07\xa9\xa5\xf6"\x80\xb8\xa3\x8ex\xe2\x8f\xca\x80\xd43\xc9\xcf\xd6\x94\n\x1a\x06?\x1d=\xa8\xe4\xd2\x04.>\xb4\xe01\x8a7\x18\xec{\xd2\xe3\'\x9cP\xf5\x0e\xe2\xe2\x9c\x07\xe9In6.:\xfbR\xe3\x07\xfc\xf5\xa0B\x81\xfa\xd3\xf0O\xe1J\xfa\x80\xa0T\x80q\xf5\xfetu\x18\x8c\xa4\xe6\x9a\x174;\xea\x08~8\xa3\x1c\xd2[l\x08x\x02\x95\x80\xfc\xa8Z\x8cz\xaf\x1d*@\xbdqI\xdd\x80\xef\xa8\x14\x00E?\x98\x83\xe9\xde\x9d\x82*\x93\xdf@\x14\x0c\xfe5\x1b\xa1=(Ka\xc7r=\xa4u\xa9\x91\t<\x8aU44."c$\xe2\xb3u-Q-beV\x195\n<\xcd\nN\xc9\x9c\r\xc5\xcc\x97\x0e\xee\xcckS@]\xda\x82\x003\x94\x9b\xff\x00A5\xd9\x15dq\xcd\xdd\xb3MN\x1a\xd4\x0f\xe2\'\xa5h\x9cc\xaej1;\xa3\xb7\'\xdad39\x8e9\x1f<\x80M`\xdd\xea\x12\xce\xa22z\x00\x18\x8e\xe2\x8a\r\xeb\xa8g\x1f`\xcd\xebS\xc5mqq\xc40L\xf8\xfe\xe0cZn\xce\x16<Y]\xf9\xc9\x0f\xd9\xe6\x0f)\xc2\xa9\x04d\xd7Qo\xe1#\x8f\xf4\xcb\xf8\x11\x8fT\\\x13\x9am[p0\xb2ON\xd4\x0fPzW?Cp=;Q\xc1\xfc)\xc7A&\x03\x9c\x9c\xf5\xa5\xe4\x9cz\xd2\x067\xf04t\xc0\xa5}F\xc7\x0e\xc7\xad\x1f\\\xfd)\xb1\\i\xe7\x9cS;\xd3~\x80\xc7\xe7\x19<\xd2d\x8e\x80\xd2\x1a\xd8\x07\xbex\xa0s\xebE\x84;\x9e\x9e\xb4\x99\xe3\x929\xa3@\x0fZx<\xfdh`\x85=\xb1\xde\x90\x81\xcd\ry\x82\xeb\xa0\x03\x9e\xe3\xbd(\xeb\x91\xc5\x1bu\x05\xb8\xbd\x8f\xb5/9\xc9\xefs\x8aQ\x8c\xf5\xa4\x9f\x981\xd8\'\xad\x00}hL\x18\xecq\xda\x9c)\x0cv)q\xfa\xd0\xc3\xb8\xecs\xcfjx\x140\xea;\x1e\xd4b\x86\x02\xe3\xebO\xc7\xd6\x90\xd8\xecS\xd5{\xfe"\x8108\xe7"\x90/aKA\xeb\xdcv\xd3\xc8\xc5\x18\xa2\xe0\x89\x00\xa3\x04\x9eh\xba\x04L\xab\xda\x9f\xb6\x92\x06\x05On\xd4\x98\xe0\xd3\x88\x06\xdaS\x9e\x95K@\x14\x0e\xbdi\xdbI=)j8\x8b\xe5g\xb5H\x14 \xc9\xc7\x14\x9e\xe5\xdc\xc3\xd4\xb5d\x85\x19#<\xf4\xe2\xb8{\x9b\x99.$.\xccy\xadp\xf1\xb6\xb60\xc4\xcf\xa1\x08<{\x9a\xe8\xbc?\x93\x7f\xdf\xe5\x8en\x99\xfe\xe9\xadLK\x81s=\x90\xfe\xe9c\x81Z\xcc\xd1\xa0/+0\x0b\xd7\x1c\x93\xec=\xeaq\x1b\xe8wen\xd0\xa8\xcd\x19\x0e\x9b\x15\xa8\xfbu\xb3\xa1\xb8\x18Tb\x0b\x11\xf8W\x9e\xdc\x08\xc4\xd2\x08\xc3\x05$\xe3&\xaa*\xcbc\x97\x11VU\x1e\xa6\xee\x81\xa7\xd9\\\xbc\x93\xdf\x1c\xacg\xe5C\x9c\x13\xdf>\xd5\xbdu\xaf\\\xab\x18\xf4\xc8\xe0H\xa2\x18\x05\x86\x07\x1e\x82\x9cL\xde\xa4\x16\xf77\xba\x80\x12\\\xca7[\xe7n@\x18c\xd2\xaaZi\x93\xdd\xdc1y\x00 \xb6]\x8f?\x90\xaaK@0\xfb\x11\x81G8\x03\xads\xeem!\xd9\x1d\xfbb\x90\xf4\xc1\x1d~\x98\xa3K\x82a\x9e9=y\xcd\'<d\x8f\xd6\x95\xae1y\xf4\xff\x00\nA\xd7\xafJO}\xc2\xe83\xc1\xe7\xf1\xa5\xfav\xa7k\xdcL\\g\'\x9a\x8f8\'=\xff\x00\x9d\x1d@:\xf7\xebK\xcf\xaf\xff\x00\xae\x85\xa5\x83p$\x9c\xff\x00ZQ\x9f\xcf\x9a\x18&/\xaf\xff\x00\xaa\x93\xae:\xd0\xaf\xd8\x00g\x9a^Fs\xde\x84\x0cx\xc6x\xcf\xad!\xc7\xe5F\x81\xa8\x0e\xa4\x9e\xd4\xee\xd4\x0c\x07\xa8\xa0\xf0\x08\xf5\xa1\xadX\xafa\xdc\xe6\x
Wireshark 文件:https://drive.google.com/file/d/18vz1yH7yChi32iFBuyNJFVXDlAwjnb7g/view?usp=sharing
捕获的数据似乎包含重复的 UDP 数据包。这很奇怪。
这些 UDP 帧的有效负载本身以 16 位长度开头。这有点多余,因为 UDP 已经完成了帧处理。
其余数据并没有引起人们的注意。很可能是专有的。有一个标题部分不会改变。
我看到一个 JPEG 标题。 Wireshark 的十六进制转储的 ASCII 端显示实际的 ASCII,而不是 latin1 或其他任何内容,因此对于
.
以上的任何字节,它仅显示 0x7f
。这隐藏了十六进制转储中的重要信息。
我还没有扫描数据以查找其他知名签名。您可以浏览 https://en.wikipedia.org/wiki/List_of_file_signatures 并检查是否有任何有趣的内容。
这是从最后一个UDP数据包中复制出来的JPG数据。您的相机似乎看到黑暗。