-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6e1f896
commit b320733
Showing
2 changed files
with
273 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,268 @@ | ||
<!DOCTYPE html> | ||
<html lang="zh-TW"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Screen Capture</title> | ||
<!-- 引入 Google 字體 --> | ||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet"> | ||
<style> | ||
/* 重置一些預設樣式 */ | ||
* { | ||
margin: 0; | ||
padding: 0; | ||
box-sizing: border-box; | ||
} | ||
|
||
body { | ||
font-family: 'Roboto', sans-serif; | ||
background: linear-gradient(135deg, #f5f7fa, #c3cfe2); | ||
min-height: 100vh; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
padding: 20px; | ||
} | ||
|
||
h2 { | ||
margin-top: 20px; | ||
color: #333; | ||
} | ||
|
||
p { | ||
max-width: 600px; | ||
text-align: center; | ||
margin-bottom: 30px; | ||
color: #555; | ||
line-height: 1.6; | ||
} | ||
|
||
/* 按鈕樣式 */ | ||
.button { | ||
display: inline-block; | ||
padding: 12px 24px; | ||
margin: 10px; | ||
font-size: 16px; | ||
font-weight: 700; | ||
color: #fff; | ||
background: #6200ea; | ||
border: none; | ||
border-radius: 30px; | ||
cursor: pointer; | ||
transition: background 0.3s, transform 0.2s; | ||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | ||
text-align: center; | ||
text-decoration: none; | ||
} | ||
|
||
.button:hover { | ||
background: #3700b3; | ||
transform: translateY(-2px); | ||
} | ||
|
||
.button:active { | ||
background: #290a8c; | ||
transform: translateY(0); | ||
} | ||
|
||
/* 特殊樣式的下載按鈕 */ | ||
#downloadButton { | ||
background: #03dac6; | ||
} | ||
|
||
#downloadButton:hover { | ||
background: #018786; | ||
} | ||
|
||
/* 佈局 */ | ||
.container { | ||
display: flex; | ||
flex-wrap: wrap; | ||
justify-content: center; | ||
width: 100%; | ||
max-width: 1200px; | ||
gap: 40px; | ||
} | ||
|
||
.left, .right { | ||
flex: 1 1 300px; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
} | ||
|
||
video { | ||
border-radius: 15px; | ||
box-shadow: 0 4px 10px rgba(0,0,0,0.2); | ||
margin-top: 15px; | ||
max-width: 100%; | ||
height: auto; | ||
} | ||
|
||
/* 日誌區域 */ | ||
.bottom { | ||
width: 100%; | ||
max-width: 800px; | ||
margin-top: 40px; | ||
background: #fff; | ||
padding: 20px; | ||
border-radius: 15px; | ||
box-shadow: 0 4px 10px rgba(0,0,0,0.1); | ||
overflow: auto; | ||
} | ||
|
||
pre { | ||
white-space: pre-wrap; | ||
word-wrap: break-word; | ||
color: #333; | ||
} | ||
|
||
/* 響應式調整 */ | ||
@media (max-width: 768px) { | ||
.container { | ||
flex-direction: column; | ||
align-items: center; | ||
} | ||
|
||
.left, .right { | ||
width: 100%; | ||
max-width: 400px; | ||
} | ||
|
||
video { | ||
width: 100%; | ||
height: auto; | ||
} | ||
} | ||
|
||
/* 按鈕元素的樣式調整 */ | ||
button.button { | ||
font-family: 'Roboto', sans-serif; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<p> | ||
點擊 "開始錄製" 按鈕開始錄製影片幾秒鐘。您可以通過點擊 "停止錄製" 按鈕來停止錄影。"下載影片" 按鈕將下載接收到的數據(影片將以 WebM 格式下載)。 | ||
</p> | ||
|
||
<div class="container"> | ||
<div class="left"> | ||
<button id="startButton" class="button"> | ||
開始錄製 | ||
</button> | ||
<h2>預覽</h2> | ||
<video id="preview" autoplay muted></video> | ||
</div> | ||
<div class="right"> | ||
<button id="stopButton" class="button" disabled> | ||
停止錄製 | ||
</button> | ||
<h2>錄影結果</h2> | ||
<video id="recording" controls></video> | ||
<a id="downloadButton" class="button" href="#" download="recording.webm" style="display: none;"> | ||
下載影片 | ||
</a> | ||
</div> | ||
</div> | ||
|
||
<div class="bottom"> | ||
<h2>日誌</h2> | ||
<pre id="log">等待操作...</pre> | ||
</div> | ||
|
||
<!-- JavaScript 功能實現 --> | ||
<script> | ||
const startButton = document.getElementById('startButton'); | ||
const stopButton = document.getElementById('stopButton'); | ||
const downloadButton = document.getElementById('downloadButton'); | ||
const preview = document.getElementById('preview'); | ||
const recording = document.getElementById('recording'); | ||
const log = document.getElementById('log'); | ||
|
||
let mediaRecorder; | ||
let recordedChunks = []; | ||
|
||
// 檢查瀏覽器是否支持MediaRecorder | ||
if (!('MediaRecorder' in window)) { | ||
log.textContent = '抱歉,您的瀏覽器不支持錄影功能。'; | ||
startButton.disabled = true; | ||
} | ||
const displayMediaOptions = { | ||
video: { | ||
displaySurface: "browser", | ||
}, | ||
audio: { | ||
suppressLocalAudioPlayback: false, | ||
}, | ||
preferCurrentTab: false, | ||
selfBrowserSurface: "exclude", | ||
systemAudio: "include", | ||
surfaceSwitching: "include", | ||
monitorTypeSurfaces: "include", | ||
}; | ||
|
||
startButton.addEventListener('click', async () => { | ||
log.textContent = '請求攝像頭和麥克風權限...'; | ||
startButton.disabled = true; | ||
stopButton.disabled = false; | ||
downloadButton.style.display = 'none'; | ||
recording.src = ''; | ||
try { | ||
const stream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions); | ||
preview.srcObject = stream; | ||
const options = { mimeType: 'video/webm; codecs=vp9' }; | ||
mediaRecorder = new MediaRecorder(stream, options); | ||
|
||
mediaRecorder.ondataavailable = event => { | ||
if (event.data.size > 0) { | ||
recordedChunks.push(event.data); | ||
log.textContent += '\n獲取錄影數據...'; | ||
} | ||
}; | ||
|
||
mediaRecorder.onstart = () => { | ||
log.textContent += '\n錄影開始。'; | ||
}; | ||
|
||
mediaRecorder.onstop = () => { | ||
log.textContent += '\n錄影停止,處理錄影數據。'; | ||
const blob = new Blob(recordedChunks, { type: 'video/webm' }); | ||
const url = URL.createObjectURL(blob); | ||
recording.src = url; | ||
downloadButton.href = url; | ||
downloadButton.style.display = 'inline-block'; | ||
recordedChunks = []; | ||
log.textContent += '\n錄影完成。'; | ||
}; | ||
|
||
mediaRecorder.onerror = event => { | ||
log.textContent += `\n錄影錯誤: ${event.error}`; | ||
}; | ||
|
||
mediaRecorder.start(); | ||
log.textContent += '\n正在錄影中...'; | ||
} catch (err) { | ||
log.textContent = `無法訪問攝像頭和麥克風: ${err}`; | ||
startButton.disabled = false; | ||
stopButton.disabled = true; | ||
} | ||
}); | ||
|
||
stopButton.addEventListener('click', () => { | ||
if (mediaRecorder && mediaRecorder.state !== 'inactive') { | ||
mediaRecorder.stop(); | ||
const stream = preview.srcObject; | ||
if (stream) { | ||
const tracks = stream.getTracks(); | ||
tracks.forEach(track => track.stop()); | ||
preview.srcObject = null; | ||
} | ||
stopButton.disabled = true; | ||
startButton.disabled = false; | ||
log.textContent += '\n已發出停止錄影命令。'; | ||
} | ||
}); | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters