1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
|
---
title: MediaDevices.getUserMedia()
slug: Web/API/MediaDevices/getUserMedia
translation_of: Web/API/MediaDevices/getUserMedia
---
<div>{{APIRef("WebRTC")}}</div>
<p><span class="notranslate"><span class="seoSummary">La méthode <code><strong>MediaDevices.getUserMedia()</strong></code> invite l'utilisateur à autoriser l'utilisation d'une entrée multimédia qui produit un </span></span> <span class="seoSummary">{{domxref("MediaStream")}}</span> <span class="notranslate"><span class="seoSummary"> avec des pistes contenant les types de médias demandés.</span></span> <span class="notranslate"> Ce flux peut inclure, par exemple, une piste vidéo (produite par une source matérielle ou vidéo virtuelle telle qu'une caméra, un dispositif d'enregistrement vidéo, un service de partage d'écran, etc.), une piste audio (de la même manière, produite par une source physique ou Source audio virtuelle comme un microphone, convertisseur A / D ou similaire) et éventuellement d'autres types de piste.</span></p>
<p><span class="notranslate">Il renvoie un </span> {{jsxref("Promise")}} <span class="notranslate"> qui est résolu avec succès si l'utilisateur donne son autorisation;</span> <span class="notranslate"> </span> {{domxref("MediaStream")}} <span class="notranslate"> est fourni à ce moment-là.</span> <span class="notranslate"> Si l'utilisateur refuse ou si le média correspondant n'est pas disponible, le </span> {{jsxref("Promise")}} <span class="notranslate"> est rejetée avec respectivement <code>PermissionDeniedError</code> ou <code>NotFoundError</code>.</span></p>
<div class="note">
<p><span class="notranslate">Il est possible que le </span> {{jsxref("Promise")}} <span class="notranslate"> renvoyé ne soit <em>ni</em> résolu ni rejeté, car l'utilisateur n'est pas tenu de faire un choix.</span> .</p>
</div>
<p><span class="notranslate">Généralement, vous accédez à l'objet </span> {{domxref("MediaDevices")}} <span class="notranslate"> avec </span> {{domxref("navigator.mediaDevices")}} <span class="notranslate"> , comme ceci:</span></p>
<pre class="brush: js">navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
/* use the stream */
}).catch(function(err) {
/* handle the error */
});</pre>
<h2 id="Syntaxe">Syntaxe</h2>
<pre class="syntaxbox">var <em>promise</em> = navigator.mediaDevices.getUserMedia(<em>constraints</em>);
</pre>
<h3 id="Paramètres"><span class="notranslate">Paramètres</span></h3>
<dl>
<dt><code>constraints</code></dt>
<dd>
<p><span class="notranslate">Un objet </span> {{domxref("MediaStreamConstraints")}} <span class="notranslate"> spécifiant les types de supports à demander, ainsi que toutes les exigences pour chaque type.</span></p>
<p><span class="notranslate">Le paramètre constraints est un objet <code>MediaStreamConstraints</code> avec deux membres: <code>video</code> et <code>audio</code> , décrivant les types de média demandés.</span> <span class="notranslate"> L'un ou l'autre ou les deux doivent être spécifiés.</span> <span class="notranslate"> Si le navigateur ne trouve pas toutes les pistes multimédia avec les types spécifiés qui répondent aux contraintes fournies, la promesse renvoyée est rejetée avec <code>NotFoundError</code> .</span></p>
<p><span class="notranslate">Les demandes suivantes sont audio et vidéo sans aucune exigence spécifique:</span></p>
<pre class="brush: js">{ audio: true, video: true }</pre>
<p><span class="notranslate">Si <code>true</code> est spécifié pour un type de média, le flux résultant est <em>requis</em> pour obtenir ce type de piste.</span> <span class="notranslate"> Si on ne peut pas l'obtenir pour une raison quelconque, l'appel à <code>getUserMedia()</code> entraînera une erreur.</span></p>
<p><span class="notranslate">Alors que les informations sur les caméras et les microphones d'un utilisateur sont inaccessibles pour des raisons de confidentialité, une application peut demander les capacités de caméra et de microphone dont elle a besoin en utilisant des contraintes supplémentaires.</span> <span class="notranslate"> Ce qui suit exprime une préférence pour la résolution de la caméra 1280x720:</span></p>
<pre class="brush: js">{
audio: true,
video: { width: 1280, height: 720 }
}</pre>
<p id="successCallback"><span class="notranslate">Le navigateur essaiera d'honorer cela, mais peut renvoyer d'autres résolutions si une correspondance exacte n'est pas disponible, ou si l'utilisateur l'annule.</span></p>
<p><span class="notranslate">Pour <em>exiger</em> une capacité, utilisez les mots-clés <code>min</code> , <code>max</code> ou <code>exact</code> (aka <code>min == max</code> ).</span> <span class="notranslate"> Ce qui suit exige une résolution minimale de 1280x720:</span></p>
<pre class="brush: js">{
audio: true,
video: {
width: { min: 1280 },
height: { min: 720 }
}
}</pre>
<p><span class="notranslate">Si aucune caméra n'existe avec cette résolution ou plus haut, le </span> {{jsxref("Promise")}} <span class="notranslate"> retourné sera rejeté avec <code>OverconstrainedError</code>.</span></p>
<p><span class="notranslate">La raison de la différence de comportement est que les mots clés <code>min</code> , <code>max</code> et <code>exact</code> sont intrinsèquement obligatoires, alors que les valeurs simples et un mot-clé appelé <code>ideal</code> ne le sont pas.</span> <span class="notranslate"> Voici un exemple plus complet:</span></p>
<pre class="brush: js">{
audio: true,
video: {
width: { min: 1024, ideal: 1280, max: 1920 },
height: { min: 776, ideal: 720, max: 1080 }
}
}</pre>
<p><span class="notranslate">Une valeur <code>ideal</code> , lorsqu'elle est utilisée, a une gravité, ce qui signifie que le navigateur essaiera de trouver le réglage (et la caméra, si vous en avez plus d'une), avec les valeurs les plus proches des valeurs idéales données.</span></p>
<p><span class="notranslate">Les valeurs simples sont par nature idéales, ce qui signifie que le premier de nos exemples de résolution ci-dessus aurait pu être écrit comme ceci:</span></p>
<pre class="brush: js">{
audio: true,
video: {
width: { ideal: 1280 },
height: { ideal: 720 }
}
}</pre>
<p><span class="notranslate">Toutes les contraintes ne sont pas des nombres.</span> <span class="notranslate"> Par exemple, sur les appareils mobiles, les éléments suivants préfèrent la caméra avant (si celle-ci est disponible) sur l'arrière:</span></p>
<pre class="brush: js">{ audio: true, video: { facingMode: "user" } }</pre>
<p><span class="notranslate">Pour <em>exiger</em> la caméra arrière, utilisez:</span></p>
<pre class="brush: js">{ audio: true, video: { facingMode: { exact: "environment" } } }</pre>
</dd>
</dl>
<h3 id="Valeur_de_retour"><span class="notranslate">Valeur de retour</span></h3>
<p><span class="notranslate">Un </span> {{jsxref("Promise")}} <span class="notranslate"> qui reçoit en objet </span> {{domxref("MediaStream")}} <span class="notranslate"> lorsque les médias demandés ont été obtenus avec succès.</span></p>
<h3 id="Erreurs">Erreurs</h3>
<p><span class="notranslate">Les rejets du </span> {{jsxref("Promise")}} <span class="notranslate"> retourné sont effectués en passant un objet erreur <a href="https://translate.googleusercontent.com/translate_c?depth=1&hl=fr&prev=search&rurl=translate.google.fr&sl=en&sp=nmt4&u=https://developer.mozilla.org/en-US/docs/Web/API/DOMException&usg=ALkJrhgnRUAs3RQR8I7ulOitmhRQUlVEUA" title="L'interface DOMException représente un événement anormal (appelé exception) qui se produit en raison de l'appel d'une méthode ou de l'accès à une propriété d'une API Web."><code>DOMException</code></a> au gestionnaire d'erreurs.</span> <span class="notranslate"> Les erreurs possibles sont:</span></p>
<dl>
<dt><code>AbortError</code></dt>
<dd><span class="notranslate">Bien que l'utilisateur et le système d'exploitation aient tous deux accédé à l'équipement matériel, et qu'aucun problème de matériel ne causerait un <code>NotReadableError</code> , un problème s'est produit, ce qui a empêché l'utilisation du périphérique.</span></dd>
<dt><code>NotAllowedError</code></dt>
<dd><span class="notranslate">L'utilisateur a spécifié que l'instance de navigation actuelle n'a pas accès au périphérique;</span> <span class="notranslate"> Ou l'utilisateur a refusé l'accès pour la session en cours;</span> <span class="notranslate"> Ou l'utilisateur a refusé tout l'accès aux périphériques multimédias utilisateurs dans le monde entier.</span>
<div class="note"><span class="notranslate">Les versions plus anciennes de la spécification ont utilisé <code>SecurityError</code> pour cela à la place;</span> <span class="notranslate"> <code>SecurityError</code> a pris une nouvelle signification.</span></div>
</dd>
<dt><code>NotFoundError</code></dt>
<dd><span class="notranslate">Aucune piste multimédia du type spécifié n'a été trouvée satisfaisant les contraintes données.</span></dd>
<dt><code>NotReadableError</code></dt>
<dd><span class="notranslate">Bien que l'utilisateur ait autorisé l'utilisation des appareils correspondants, une erreur matérielle s'est produite sur le système d'exploitation, le navigateur ou le niveau de la page Web qui a empêché l'accès au périphérique.</span></dd>
<dt><code>OverConstrainedError</code></dt>
<dd><span class="notranslate">Aucun dispositif candidat répondant aux critères demandés.</span> <span class="notranslate"> L'erreur est un objet de type <code>OverconstrainedError</code> et possède une propriété de <code>constraint</code> dont la valeur de chaîne est le nom d'une contrainte impossible à honorer et une propriété <code>message</code> contenant une chaîne lisible par l'homme expliquant le problème.</span>
<div class="note"><span class="notranslate">Étant donné que cette erreur peut se produire même lorsque l'utilisateur n'a pas encore autorisé l'utilisation du périphérique sous-jacent, il peut être utilisé comme surface d'empreinte digitale.</span></div>
</dd>
<dt><code>SecurityError</code></dt>
<dd><span class="notranslate">Le support multimédia utilisateur est désactivé sur le </span> {{domxref("Document")}} <span class="notranslate"> sur lequel <code>getUserMedia()</code> été appelé.</span> <span class="notranslate"> Le mécanisme par lequel le support média utilisateur est activé/désactivé est laissé à la discrétion de l'utilisateur.</span></dd>
<dt><code>TypeError</code></dt>
<dd><span class="notranslate">La liste des contraintes spécifiées est vide ou toutes les contraintes sont définies comme <code>false</code> .</span></dd>
</dl>
<h2 id="Exemples"><span class="notranslate"><strong>Exemple</strong>s</span></h2>
<h3 id="Largeur_et_hauteur"><span class="notranslate">Largeur et hauteur</span></h3>
<p><span class="notranslate">Cet exemple donne une préférence pour la résolution de la caméra et attribue l'objet <a href="https://translate.googleusercontent.com/translate_c?depth=1&hl=fr&prev=search&rurl=translate.google.fr&sl=en&sp=nmt4&u=https://developer.mozilla.org/en-US/docs/Web/API/MediaStream&usg=ALkJrhipdR5n2jQ-BGrPTomESH_A7nof4g" title="L'interface MediaStream représente un flux de contenu multimédia. Un flux se compose de plusieurs pistes telles que des pistes vidéo ou audio. Chaque piste est spécifiée comme une instance de MediaStreamTrack."><code>MediaStream</code></a> résultant à un élément vidéo.</span></p>
<pre>// Prefer camera resolution nearest to 1280x720.
var constraints = { audio: true, video: { width: 1280, height: 720 } };
navigator.mediaDevices.getUserMedia(constraints)
.then(function(mediaStream) {
var video = document.querySelector('video');
video.srcObject = mediaStream;
video.onloadedmetadata = function(e) {
video.play();
};
})
.catch(function(err) { console.log(err.name + ": " + err.message); }); // always check for errors at the end.
</pre>
<h3 id="Utilisation_de_la_nouvelle_API_dans_les_navigateurs_plus_anciens"><span class="notranslate">Utilisation de la nouvelle API dans les navigateurs plus anciens</span></h3>
<p><span class="notranslate">Voici un exemple d'utilisation de <code>navigator.mediaDevices.getUserMedia()</code> , avec un adaptateur pour faire face aux navigateurs plus anciens.</span> <span class="notranslate"> Notez que cet adaptater ne corrige pas les différences existantes dans la syntaxe des contraintes, ce qui signifie que les contraintes ne fonctionneront pas bien dans les navigateurs.</span> <span class="notranslate"> Il est recommandé d'utiliser l'adaptateur</span> <a href="https://github.com/webrtc/adapter">adapter.js</a> <span class="notranslate"> a la place, qui gère les contraintes.</span></p>
<pre class="brush: js">// Older browsers might not implement mediaDevices at all, so we set an empty object first
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
// Some browsers partially implement mediaDevices. We can't just assign an object
// with getUserMedia as it would overwrite existing properties.
// Here, we will just add the getUserMedia property if it's missing.
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function(constraints) {
// First get ahold of the legacy getUserMedia, if present
var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// Some browsers just don't implement it - return a rejected promise with an error
// to keep a consistent interface
if (!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
}
// Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
return new Promise(function(resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
}
}
navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then(function(stream) {
var video = document.querySelector('video');
// Older browsers may not have srcObject
if ("srcObject" in video) {
video.srcObject = stream;
} else {
// Avoid using this in new browsers, as it is going away.
video.src = window.URL.createObjectURL(stream);
}
video.onloadedmetadata = function(e) {
video.play();
};
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
});
</pre>
<h3 id="Taux_d'images">Taux d'images</h3>
<p><span class="notranslate">Des cadences inférieures peuvent être souhaitables dans certains cas, comme les transmissions WebRTC avec des restrictions de bande passante.</span></p>
<pre class="brush: js">var constraints = { video: { frameRate: { ideal: 10, max: 15 } } };
</pre>
<h3 id="Caméra_avant_et_arrière"><span class="notranslate">Caméra avant et arrière</span></h3>
<p><span class="notranslate">Sur les téléphones portables.</span></p>
<pre class="brush: js">var front = false;
document.getElementById('flip-button').onclick = function() { front = !front; };
var constraints = { video: { facingMode: (front? "user" : "environment") } };
</pre>
<h2 id="Permissions">Permissions</h2>
<p><span class="notranslate">Pour utiliser <code>getUserMedia()</code> dans une application installable (par exemple, une <a href="https://translate.googleusercontent.com/translate_c?depth=1&hl=fr&prev=search&rurl=translate.google.fr&sl=en&sp=nmt4&u=https://developer.mozilla.org/en-US/Apps/Build/Building_apps_for_Firefox_OS/Firefox_OS_app_beginners_tutorial&usg=ALkJrhjjqOGYUEn75gZx3AcoQDArrosa9Q">application Firefox OS</a> ), vous devez spécifier un ou les deux champs suivants dans votre fichier manifeste:</span></p>
<pre class="brush: js">"permissions": {
"audio-capture": {
"description": "Required to capture audio using getUserMedia()"
},
"video-capture": {
"description": "Required to capture video using getUserMedia()"
}
}</pre>
<p><span class="notranslate">Voir </span> <a href="https://developer.mozilla.org/en-US/Apps/Developing/App_permissions#audio-capture">permission: audio-capture</a> <span class="notranslate"> et </span> <a href="https://developer.mozilla.org/en-US/Apps/Developing/App_permissions#video-capture">permission: video-capture</a> <span class="notranslate"> pour plus d'informations.</span></p>
<h2 id="Specifications">Specifications</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td>{{SpecName('Media Capture', '#dom-mediadevices-getusermedia', 'MediaDevices.getUserMedia()')}}</td>
<td>{{Spec2('Media Capture')}}</td>
<td>Initial definition</td>
</tr>
</tbody>
</table>
<h2 id="Browser_compatibility">Browser compatibility</h2>
<div>{{CompatibilityTable}}</div>
<div id="compat-desktop">
<table class="compat-table">
<tbody>
<tr>
<th>Feature</th>
<th>Chrome</th>
<th>Edge</th>
<th>Firefox (Gecko)</th>
<th>Microsoft Edge</th>
<th>Internet Explorer</th>
<th>Opera</th>
<th>Safari (WebKit)</th>
</tr>
<tr>
<td>Basic support</td>
<td>{{CompatChrome(53.0)}}<sup>[1][3]</sup></td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatGeckoDesktop(36)}}<sup>[2][4]</sup></td>
<td>{{CompatUnknown}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatOpera(40)}}<sup>[1]</sup></td>
<td>{{CompatNo}}</td>
</tr>
<tr>
<td>Promises</td>
<td>{{CompatChrome(53.0)}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatGeckoDesktop(38)}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatNo}}</td>
</tr>
</tbody>
</table>
</div>
<div id="compat-mobile">
<table class="compat-table">
<tbody>
<tr>
<th>Feature</th>
<th>Android Webview</th>
<th>Chrome for Android</th>
<th>Edge</th>
<th>Firefox Mobile (Gecko)</th>
<th>IE Phone</th>
<th>Opera Mobile</th>
<th>Safari Mobile</th>
</tr>
<tr>
<td>Basic support</td>
<td>{{CompatChrome(53.0)}}<sup>[1][3]</sup></td>
<td>{{CompatChrome(53.0)}}<sup>[1][3]</sup></td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatGeckoMobile(36)}} <sup>[2]</sup></td>
<td>{{CompatNo}}</td>
<td>{{CompatOperaMobile(40)}}<sup>[1]</sup></td>
<td>{{CompatNo}}</td>
</tr>
<tr>
<td>Promises</td>
<td>{{CompatChrome(53.0)}}</td>
<td>{{CompatChrome(53.0)}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatGeckoMobile(38)}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatNo}}</td>
</tr>
</tbody>
</table>
</div>
<p>[1] <span class="notranslate"> Les versions plus anciennes de Chrome et Opera implémentent <code>navigator.webkitGetUserMedia</code> , la version préfixée de la méthode </span> {{domxref("navigator.getUserMedia")}} <span class="notranslate"> .</span></p>
<p><span class="notranslate">De la version 47 à la 52, l'interface promise n'est disponible que via </span> <a href="https://github.com/webrtc/adapter">adapter.js</a><span class="notranslate">, ou en utilisant les options flag</span> <a>chrome://flags/#enable-experimental-web-platform-features</a> <span class="notranslate">.</span> <span class="notranslate"> À partir de la version 53, l'interface promise est activée par défaut, même si cette interface n'est toujours pas disponible via le <code>navigator</code> .</span></p>
<p>[2] <span class="notranslate">Les anciennes versions de Firefox implémentent <code>navigator.mozGetUserMedia()</code> , la version préfixée de la méthode </span> {{domxref("navigator.getUserMedia")}} <span class="notranslate"> .</span></p>
<p><span class="notranslate">La version prometteuse de cette méthode et la syntaxe de contrainte décrites ici sont disponibles à partir de Firefox 38. Les versions antérieures (32-37) ont utilisé une syntaxe de contrainte périmée, mais la syntaxe décrite ici, ainsi que l'interface promise est Disponible à l'aide de </span> <a href="https://github.com/webrtc/adapter">adapter.js</a> <span class="notranslate">.</span></p>
<p><span class="notranslate">Firefox 49 comprend des modifications pour mettre les </span> {{anch("Errors", "erreurs")}} <span class="notranslate"> possibles à jour avec la spécification, y compris la modification de la signification de <code>SecurityError</code> .</span> <span class="notranslate"> De plus, si les pistes vidéo et audio sont demandées, <code>getUserMedia()</code> échoue maintenant pour ne pas pouvoir accéder aux deux.</span> <span class="notranslate"> Auparavant, il créerait un flux qui disposait de la partie réussie des médias.</span> <span class="notranslate"> Par exemple, si l'utilisateur dispose d'un microphone mais pas d'appareil photo (ou refusé l'accès à la caméra), les versions précédentes de Firefox renverraient un flux avec une piste audio mais pas de vidéo.</span> <span class="notranslate"> Maintenant, cela entraîne correctement une erreur.</span></p>
<p><span class="notranslate">Opera utilise une syntaxe de contrainte périmée, mais la syntaxe décrite ici est disponible via </span> <a href="https://github.com/webrtc/adapter">adapter.js</a>.</p>
<p>[3] <span class="notranslate">Chrome lance une erreur si la page qui sert le script est chargée d'origine non sécurisée (c'est-à-dire HTTP).</span></p>
<p>[4] <span class="notranslate">Avant Firefox 55, <code>getUserMedia()</code> renvoie incorrectement <code>NotSupportedError</code> lorsque la liste des contraintes spécifiées est vide ou que toutes les contraintes sont définies comme <code>false</code> .</span> <span class="notranslate"> À partir de Firefox 55, cette situation appelle correctement le gestionnaire d'échec avec un <code>TypeError</code> .</span></p>
<h2 id="Voir_également"><span class="notranslate">Voir également</span></h2>
<ul>
<li><span class="notranslate">L'ancien API</span> {{domxref("navigator.getUserMedia()")}}.</li>
<li>{{domxref("mediaDevices.enumerateDevices()")}}: <span class="notranslate">Apprenez les types et le nombre de périphériques que l'utilisateur dispose.</span></li>
<li><a href="/en-US/docs/Web/API/WebRTC_API">WebRTC API</a></li>
<li><a href="/en-US/docs/Web/API/Media_Streams_API">Media Capture and Streams API (Media Streams)</a></li>
<li><a href="/en-US/docs/Web/API/WebRTC_API/Taking_still_photos">Taking webcam photos</a>: <span class="notranslate">un didacticiel sur l'utilisation de <code>getUserMedia()</code> pour prendre des photos plutôt que de la vidéo.</span></li>
</ul>
|