-
-
Notifications
You must be signed in to change notification settings - Fork 6
feat(HikVision): add CapturePicture function #865
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -280,7 +280,7 @@ public async Task<bool> OpenSound() | |||||||||||||||||||||||
| if (IsLogin && IsRealPlaying) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| var code = await InvokeAsync<int>("openSound", Id); | ||||||||||||||||||||||||
| ret = code == 0; | ||||||||||||||||||||||||
| ret = code == 100; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| return ret; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
@@ -295,7 +295,7 @@ public async Task<bool> CloseSound() | |||||||||||||||||||||||
| if (IsLogin && IsRealPlaying) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| var code = await InvokeAsync<int>("closeSound", Id); | ||||||||||||||||||||||||
| ret = code == 0; | ||||||||||||||||||||||||
| ret = code == 100; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| return ret; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
@@ -311,8 +311,60 @@ public async Task<bool> SetVolume(int value) | |||||||||||||||||||||||
| if (IsLogin && IsRealPlaying) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| var code = await InvokeAsync<int>("setVolume", Id, Math.Max(0, Math.Min(100, value))); | ||||||||||||||||||||||||
| ret = code == 0; | ||||||||||||||||||||||||
| ret = code == 100; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| return ret; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
| /// 抓图方法返回 Url | ||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
| /// <returns></returns> | ||||||||||||||||||||||||
| public async Task CapturePictureAndDownload() | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| if (IsLogin && IsRealPlaying) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| await InvokeVoidAsync("capturePictureAndDownload", Id); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| private TaskCompletionSource<IJSStreamReference?>? _captureTaskCompletionSource = null; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||
| /// 抓图方法返回 Url | ||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||
|
Comment on lines
+333
to
+335
|
||||||||||||||||||||||||
| /// <returns></returns> | ||||||||||||||||||||||||
| public async Task<IJSStreamReference?> CapturePicture(CancellationToken token = default) | ||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (complexity): Consider simplifying the new capture APIs by returning the JS stream directly from The new capture APIs add avoidable state and complexity. You can keep the functionality while simplifying the flow and removing concurrency hazards. 1. Remove the shared
|
||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| IJSStreamReference? ret = null; | ||||||||||||||||||||||||
| if (IsLogin && IsRealPlaying) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| _captureTaskCompletionSource = new(); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| try | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| await InvokeVoidAsync("capturePicture", token, Id); | ||||||||||||||||||||||||
| ret = await _captureTaskCompletionSource.Task; | ||||||||||||||||||||||||
|
Comment on lines
+346
to
+347
|
||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| catch (Exception ex) | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| _captureTaskCompletionSource.SetException(ex); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Comment on lines
+344
to
+352
|
||||||||||||||||||||||||
| try | |
| { | |
| await InvokeVoidAsync("capturePicture", token, Id); | |
| ret = await _captureTaskCompletionSource.Task; | |
| } | |
| catch (Exception ex) | |
| { | |
| _captureTaskCompletionSource.SetException(ex); | |
| } | |
| await InvokeVoidAsync("capturePicture", token, Id); | |
| ret = await _captureTaskCompletionSource.Task; |
Copilot
AI
Dec 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TriggerReceivePictureStream method is never called from JavaScript, making it dead code. Since the capturePicture JavaScript function returns a value directly rather than using a callback pattern, this method should be removed along with the _captureTaskCompletionSource field (line 331).
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -355,7 +355,7 @@ export async function openSound(id) { | |||||||||
| return 101; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| let code = 0; | ||||||||||
| let code = 100; | ||||||||||
| try { | ||||||||||
| await WebVideoCtrl.I_OpenSound(iWndIndex); | ||||||||||
| } | ||||||||||
|
|
@@ -374,7 +374,7 @@ export async function closeSound(id) { | |||||||||
| return 101; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| let code = 0; | ||||||||||
| let code = 100; | ||||||||||
| try { | ||||||||||
| await WebVideoCtrl.I_CloseSound(iWndIndex); | ||||||||||
| } | ||||||||||
|
|
@@ -398,7 +398,7 @@ export async function setVolume(id, value) { | |||||||||
| v = 50; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| let code = 0; | ||||||||||
| let code = 100; | ||||||||||
| try { | ||||||||||
| await WebVideoCtrl.I_SetVolume(Math.min(100, Math.max(0, v))); | ||||||||||
| } | ||||||||||
|
|
@@ -409,6 +409,63 @@ export async function setVolume(id, value) { | |||||||||
| return code; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| export async function capturePicture(id) { | ||||||||||
| const vision = Data.get(id); | ||||||||||
| const { realPlaying } = vision; | ||||||||||
|
|
||||||||||
| if (realPlaying !== true) { | ||||||||||
| return ""; | ||||||||||
|
||||||||||
| return ""; | |
| return null; |
Copilot
AI
Dec 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function doesn't explicitly return a value when base64 is falsy (line 422-425). This results in an implicit undefined return. For clarity and consistency with error handling (line 428), explicitly return null after the if block to handle the case where I_CapturePicData() returns a falsy value.
| } | |
| } | |
| return null; |
Copilot
AI
Dec 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The MIME type specified in the data URI is hardcoded as 'image/jpg', but the correct MIME type for JPEG images is 'image/jpeg'. While some browsers may accept 'image/jpg', using the standard 'image/jpeg' ensures better compatibility.
| anchorElement.href = `data:image/jpg;base64,${base64}`; | |
| anchorElement.href = `data:image/jpeg;base64,${base64}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment incorrectly states "抓图方法返回 Url" (Capture method returns URL), but this method triggers a download and returns void, not a URL. The comment should be updated to accurately describe that it captures and downloads the picture.